-
Notifications
You must be signed in to change notification settings - Fork 30k
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
http2: fix missing 'timeout' event emit in request and response #20918
http2: fix missing 'timeout' event emit in request and response #20918
Conversation
A timeout in a http2 stream should emit a 'timeout' event also on request and response object. If there is no listener on stream, request or response, stream should immediately be destroyed. Fixes: nodejs#20079
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.
Hi @DaAitch — thanks for working on this. I would say that this might be the slightly wrong approach. We could simplify this by just listening to the timeout even in req
and res
. From there we would have to make sure any logic matches what we have on the http
side in terms of whether we destroy the stream/session. There are some "complexities" in how the http
module handles timeouts in relation to whether the req
& res
are complete or not.
I'm currently in the midst of travelling but would be happy to provide more info when I have a bit more time.
I have also investigated on that, but in this case, we cannot find out, if there is no listener to
|
@@ -12,6 +12,10 @@ server.on('request', (req, res) => { | |||
req.setTimeout(msecs, common.mustCall(() => { | |||
res.end(); | |||
})); | |||
|
|||
res.on('timeout', common.mustCall()); | |||
req.on('timeout', common.mustCall()); |
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.
Can you please add some assertions that verifies that 'timeout'
is not emitted?
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.
@mcollina sure I can. You mean between the setTimeout
call and its callback, there should be no timeout
events on req and res?
if (component.emit('timeout')) { | ||
hasTimeoutCallback = true; | ||
} | ||
} |
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 would just check if if(!this.emit('timeout')) { this.session.destroy() }
. It would need a test on the change in http2 core behavior.
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.
stream, headers, flags, rawHeaders) { | ||
const server = this; | ||
const request = new ServerRequest(stream, headers, undefined, rawHeaders); | ||
const response = new ServerResponse(stream); | ||
|
||
stream[kStreamEventsComposite].push(request); | ||
stream[kStreamEventsComposite].push(response); |
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.
Instead of adding things to an array, I would add an event listener to 'timeout'
on the stream.
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'm still thinking about this. Hopefully can provide more insight after the summit. |
An alternative fix landed in #22252 |
A timeout in a http2 stream should emit a 'timeout' event also on
request and response object. If there is no listener on stream,
request or response, stream should immediately be destroyed.
Fixes: #20079
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes