-
Notifications
You must be signed in to change notification settings - Fork 30.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test: http2 rstStream duplicate call #16217
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Just a minor nit.
req._destroy = common.mustCall(req._destroy.bind(req), 2); | ||
|
||
client.rstStream(req, 0); | ||
// redundant call to rstStream to test rst won't be called again | ||
client.rstStream(req, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you call the second client.rstStream
with a different code, you could then verify that the rstCode
didn't get set to the 2nd incorrect code (the strictEqual
check below will do the job). Right now it's a bit ambiguous as to whether it does or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated the second call to send different code (number 1) which is not updated in req.rstCode
@@ -925,7 +925,7 @@ class Http2Session extends EventEmitter { | |||
'number'); | |||
} | |||
|
|||
if (this[kState].rst) { | |||
if (stream[kState].rst) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! :-)
This commit fixes an issue with rstStream() which checked incorrect value of rst. It also adds a test case for this fix Refs: nodejs#14985
7e7f4d6
to
810edb8
Compare
@@ -15,12 +15,15 @@ server.on('listening', common.mustCall(() => { | |||
const client = h2.connect(`http://localhost:${server.address().port}`); | |||
|
|||
const req = client.request({ ':path': '/' }); | |||
// make sure that destroy is called twice | |||
req._destroy = common.mustCall(req._destroy.bind(req), 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am a bit lost in how this is possible, in theory it is protected from running _destroy
twice: https://github.com/nodejs/node/blob/master/lib/internal/streams/destroy.js#L10-L30
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was confusing for me too.
The two instances where stream.destroy()
is called are:
- in first call of rstStream()
node/lib/internal/http2/core.js
Line 631 in ff747e3
stream.destroy(); - in second call of rstStream()
node/lib/internal/http2/core.js
Line 931 in ff747e3
stream.destroy();
This might translate to two calls of req._destroy
?
I've run the test on repeat 100 times to confirm that it it succeeds using the following command:
> python tools/test.py -J --mode=release parallel/test-http2-client-rststream-before-connect --repeat 100
[00:06|% 100|+ 100|- 0]: Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe @mcollina is right. I think what's happening is that this line is accounting for the 2 triggers of _destroy:
node/lib/internal/http2/core.js
Lines 1494 to 1498 in ff747e3
if (this[kID] === undefined) { | |
debug(`[${sessionName(session[kType])}] queuing destroy for new stream`); | |
this.once('ready', this._destroy.bind(this, err, callback)); | |
return; | |
} |
The reason that it's different than before is because the declaration was moved before client.rstStream()
instead of after. I think that stream.destroy()
isn't even necessary and it should just be the empty return;
.
ping @jasnell — any thoughts re: whether that stream.destroy()
serves an actual purpose?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've run the test on repeat 100 times
@trivikr the test might be passing, but I'm wondering if the actual behavior is correct.
I don't think that calling rstStream()
twice should destroy the stream. It seems a not needed side effect. I think it should throw.
node/lib/internal/http2/core.js
Lines 929 to 931 in ff747e3
// rst has already been called, do not call again, | |
// skip straight to destroy | |
stream.destroy(); |
cc @jasnell
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll dig in on this a bit more later on today
I would argue that this actually is a http2 fix and not a test change. So the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just making it explicit this shouldn't land until the _destroy
situation is addressed, one way or another.
Any update on this request? |
Fixed in #16753 |
This commit fixes an issue with rstStream() which checked incorrect value of rst. It also adds a test case for this fix
node/lib/internal/http2/core.js
Lines 928 to 933 in 411695e
Refs: #14985
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
test, http2