Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 34.2k
http2: fix endless loop when write an empty string#18673
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
Uh oh!
There was an error while loading. Please reload this page.
Conversation
XadillaX commented Feb 9, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
lib/internal/http2/core.js Outdated
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.
The first piece of the conditional is always true; Also, you’d still need to call cb.
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 confused that is the logic below the same?
req.write('');req.end();vs
req.end();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.
That means can I actully ignore empty string stream?
lib/internal/http2/core.js Outdated
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.
(Basically the same comment, except that the first piece of the conditional is never true; data is an array)
If we do `req.write("")` (an empty string) on Http2Stream, the gather logic will be messed up: ``` while ((src_length = nghttp2_session_mem_send(session_, &src)) > 0){printf("write\n"); DEBUG_HTTP2SESSION2(this, "nghttp2 has %d bytes to send", src_length); CopyDataIntoOutgoing(src, src_length)} ``` The logic above is in function `Http2Session::SendPendingData` under src/node_http2.cc. This `while` will be endless when an empty string is inside because `src_length` will always be 9. And then the main event loop thread will be blocked and the memory used will be larger and larger. This pull request is to ignore empty string or buffer in `_write()` and `_writev()` of Http2Stream. Fixes: nodejs#18169 Refs: https://github.com/nodejs/node/blob/v9.5.0/src/node_http2.cc#L1481-L1484 Refs: https://github.com/nodejs/node/blob/v9.5.0/lib/_http_outgoing.js#L659-L661XadillaX commented Feb 11, 2018
@addaleax I've updated the code. |
addaleax commented Feb 11, 2018
@XadillaX But this still wouldn’t send out an empty frame, like we’d expect, right? I think this line is the reason why we don’t tell nghttp2 to defer the frames: Line 2232 in a1bab82
The queue isn’t empty when we schedule an empty write, even though we don’t have any data available. Maybe we can just drop the last check in that conditional? |
XadillaX commented Feb 12, 2018 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
addaleax commented Feb 12, 2018
@XadillaX You’re right, and this way is certainly an approach to fix this bug. I’d have a preference for fixing it on the native level, though:
If you want, you can still make the case for not sending empty data frames on the HTTP/2 level, but that should still be done as part of the implementation, not part of the streams API. |
addaleax commented Feb 16, 2018
Hm … @XadillaX any further thoughts on this one? |
addaleax commented Feb 22, 2018
XadillaX commented Feb 24, 2018
@addaleax Sorry for late reply because of Chinese Spring Festival. I think you're right, if we can solve this issue in C++, then in C++. |
BridgeAR commented Mar 2, 2018
PR-URL: #18924Fixes: #18169 Refs: #18673 Refs: https://github.com/nodejs/node/blob/v9.5.0/src/node_http2.cc#L1481-L1484 Refs: https://github.com/nodejs/node/blob/v9.5.0/lib/_http_outgoing.js#L659-L661 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Khaidi Chu <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Refs: #18673 PR-URL: #18924 Refs: #18673 Refs: https://github.com/nodejs/node/blob/v9.5.0/src/node_http2.cc#L1481-L1484 Refs: https://github.com/nodejs/node/blob/v9.5.0/lib/_http_outgoing.js#L659-L661 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
PR-URL: nodejs#18924Fixes: nodejs#18169 Refs: nodejs#18673 Refs: https://github.com/nodejs/node/blob/v9.5.0/src/node_http2.cc#L1481-L1484 Refs: https://github.com/nodejs/node/blob/v9.5.0/lib/_http_outgoing.js#L659-L661 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Khaidi Chu <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Refs: nodejs#18673 PR-URL: nodejs#18924 Refs: nodejs#18673 Refs: https://github.com/nodejs/node/blob/v9.5.0/src/node_http2.cc#L1481-L1484 Refs: https://github.com/nodejs/node/blob/v9.5.0/lib/_http_outgoing.js#L659-L661 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
PR-URL: nodejs#18924Fixes: nodejs#18169 Refs: nodejs#18673 Refs: https://github.com/nodejs/node/blob/v9.5.0/src/node_http2.cc#L1481-L1484 Refs: https://github.com/nodejs/node/blob/v9.5.0/lib/_http_outgoing.js#L659-L661 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Khaidi Chu <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Refs: nodejs#18673 PR-URL: nodejs#18924 Refs: nodejs#18673 Refs: https://github.com/nodejs/node/blob/v9.5.0/src/node_http2.cc#L1481-L1484 Refs: https://github.com/nodejs/node/blob/v9.5.0/lib/_http_outgoing.js#L659-L661 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Backport-PR-URL: #20456 PR-URL: #18924Fixes: #18169 Refs: #18673 Refs: https://github.com/nodejs/node/blob/v9.5.0/src/node_http2.cc#L1481-L1484 Refs: https://github.com/nodejs/node/blob/v9.5.0/lib/_http_outgoing.js#L659-L661 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Khaidi Chu <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Refs: #18673 Backport-PR-URL: #20456 PR-URL: #18924 Refs: #18673 Refs: https://github.com/nodejs/node/blob/v9.5.0/src/node_http2.cc#L1481-L1484 Refs: https://github.com/nodejs/node/blob/v9.5.0/lib/_http_outgoing.js#L659-L661 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
PR-URL: nodejs#18924Fixes: nodejs#18169 Refs: nodejs#18673 Refs: https://github.com/nodejs/node/blob/v9.5.0/src/node_http2.cc#L1481-L1484 Refs: https://github.com/nodejs/node/blob/v9.5.0/lib/_http_outgoing.js#L659-L661 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Khaidi Chu <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Refs: nodejs#18673 PR-URL: nodejs#18924 Refs: nodejs#18673 Refs: https://github.com/nodejs/node/blob/v9.5.0/src/node_http2.cc#L1481-L1484 Refs: https://github.com/nodejs/node/blob/v9.5.0/lib/_http_outgoing.js#L659-L661 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Backport-PR-URL: #20456 PR-URL: #18924Fixes: #18169 Refs: #18673 Refs: https://github.com/nodejs/node/blob/v9.5.0/src/node_http2.cc#L1481-L1484 Refs: https://github.com/nodejs/node/blob/v9.5.0/lib/_http_outgoing.js#L659-L661 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Khaidi Chu <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Refs: #18673 Backport-PR-URL: #20456 PR-URL: #18924 Refs: #18673 Refs: https://github.com/nodejs/node/blob/v9.5.0/src/node_http2.cc#L1481-L1484 Refs: https://github.com/nodejs/node/blob/v9.5.0/lib/_http_outgoing.js#L659-L661 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Backport-PR-URL: #20456 PR-URL: #18924Fixes: #18169 Refs: #18673 Refs: https://github.com/nodejs/node/blob/v9.5.0/src/node_http2.cc#L1481-L1484 Refs: https://github.com/nodejs/node/blob/v9.5.0/lib/_http_outgoing.js#L659-L661 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Khaidi Chu <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
Refs: #18673 Backport-PR-URL: #20456 PR-URL: #18924 Refs: #18673 Refs: https://github.com/nodejs/node/blob/v9.5.0/src/node_http2.cc#L1481-L1484 Refs: https://github.com/nodejs/node/blob/v9.5.0/lib/_http_outgoing.js#L659-L661 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
If we do
req.write("")(an empty string) on Http2Stream, the gatherlogic will be messed up:
The logic above is in function
Http2Session::SendPendingDataundersrc/node_http2.cc. This
whilewill be endless when an empty string isinside because
src_lengthwill always be 9.And then the main event loop thread will be blocked and the memory used
will be larger and larger.
This pull request is to ignore empty string or buffer in
_write()and_writev()of Http2Stream.Fixes: #18169
Refs: https://github.com/nodejs/node/blob/v9.5.0/src/node_http2.cc#L1481-L1484
Refs: https://github.com/nodejs/node/blob/v9.5.0/lib/_http_outgoing.js#L659-L661
Checklist
make -j4 testpassesAffected core subsystem(s)
http2