| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 3a1ee94 commit 316354e
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1109,19 +1109,25 @@ function finishSessionClose(session, error) { | |||
| 1109 | 1109 | cleanupSession(session); | |
| 1110 | 1110 | ||
| 1111 | 1111 | if (socket && !socket.destroyed) { | |
| 1112 | + socket.on('close', () => { | ||
| 1113 | + emitClose(session, error); | ||
| 1114 | + }); | ||
| 1115 | + if (session.closed) { | ||
| 1116 | + // If we're gracefully closing the socket, call resume() so we can detect | ||
| 1117 | + // the peer closing in case binding.Http2Session is already gone. | ||
| 1118 | + socket.resume(); | ||
| 1119 | + } | ||
| 1120 | + | ||
| 1112 | 1121 | // Always wait for writable side to finish. | |
| 1113 | 1122 | socket.end((err) => { | |
| 1114 | 1123 | debugSessionObj(session, 'finishSessionClose socket end', err, error); | |
| 1115 | - // Due to the way the underlying stream is handled in Http2Session we | ||
| 1116 | - // won't get graceful Readable end from the other side even if it was sent | ||
| 1117 | - // as the stream is already considered closed and will neither be read | ||
| 1118 | - // from nor keep the event loop alive. | ||
| 1119 | - // Therefore destroy the socket immediately. | ||
| 1120 | - // Fixing this would require some heavy juggling of ReadStart/ReadStop | ||
| 1121 | - // mostly on Windows as on Unix it will be fine with just ReadStart | ||
| 1122 | - // after this 'ondone' callback. | ||
| 1123 | - socket.destroy(error); | ||
| 1124 | - emitClose(session, error); | ||
| 1124 | + // If session.destroy() was called, destroy the underlying socket. Delay | ||
| 1125 | + // it a bit to try to avoid ECONNRESET on Windows. | ||
| 1126 | + if (!session.closed) { | ||
| 1127 | + setImmediate(() => { | ||
| 1128 | + socket.destroy(error); | ||
| 1129 | + }); | ||
| 1130 | + } | ||
| 1125 | 1131 | }); | |
| 1126 | 1132 | } else { | |
| 1127 | 1133 | process.nextTick(emitClose, session, error); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -703,6 +703,11 @@ void Http2Session::Close(uint32_t code, bool socket_closed) { | |||
| 703 | 703 | Debug(this, "make done session callback"); | |
| 704 | 704 | HandleScope scope(env()->isolate()); | |
| 705 | 705 | MakeCallback(env()->ondone_string(), 0, nullptr); | |
| 706 | + if (stream_ != nullptr) { | ||
| 707 | + // Start reading again to detect the other end finishing. | ||
| 708 | + set_reading_stopped(false); | ||
| 709 | + stream_->ReadStart(); | ||
| 710 | + } | ||
| 706 | 711 | } | |
| 707 | 712 | ||
| 708 | 713 | // If there are outstanding pings, those will need to be canceled, do | |
@@ -1592,6 +1597,11 @@ void Http2Session::OnStreamAfterWrite(WriteWrap* w, int status) { | |||
| 1592 | 1597 | if (is_destroyed()) { | |
| 1593 | 1598 | HandleScope scope(env()->isolate()); | |
| 1594 | 1599 | MakeCallback(env()->ondone_string(), 0, nullptr); | |
| 1600 | + if (stream_ != nullptr) { | ||
| 1601 | + // Start reading again to detect the other end finishing. | ||
| 1602 | + set_reading_stopped(false); | ||
| 1603 | + stream_->ReadStart(); | ||
| 1604 | + } | ||
| 1595 | 1605 | return; | |
| 1596 | 1606 | } | |
| 1597 | 1607 | ||
@@ -1640,7 +1650,9 @@ void Http2Session::MaybeScheduleWrite() { | |||
| 1640 | 1650 | } | |
| 1641 | 1651 | ||
| 1642 | 1652 | void Http2Session::MaybeStopReading() { | |
| 1643 | - if (is_reading_stopped()) return; | ||
| 1653 | + // If the session is already closing we don't want to stop reading as we want | ||
| 1654 | + // to detect when the other peer is actually closed. | ||
| 1655 | + if (is_reading_stopped() || is_closing()) return; | ||
| 1644 | 1656 | int want_read = nghttp2_session_want_read(session_.get()); | |
| 1645 | 1657 | Debug(this, "wants read? %d", want_read); | |
| 1646 | 1658 | if (want_read == 0 || is_write_in_progress()) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -13,7 +13,7 @@ let session; | |||
| 13 | 13 | ||
| 14 | 14 | const countdown = new Countdown(2, () => { | |
| 15 | 15 | server.close(common.mustSucceed()); | |
| 16 | - session.destroy(); | ||
| 16 | + session.close(); | ||
| 17 | 17 | }); | |
| 18 | 18 | ||
| 19 | 19 | server.listen(0, common.mustCall(() => { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -44,17 +44,21 @@ server.on('sessionError', common.mustCall((err, session) => { | |||
| 44 | 44 | server.listen(0, common.mustCall(() => { | |
| 45 | 45 | const url = `http://localhost:${server.address().port}`; | |
| 46 | 46 | http2.connect(url) | |
| 47 | - .on('error', common.expectsError({ | ||
| 48 | - code: 'ERR_HTTP2_SESSION_ERROR', | ||
| 49 | - message: 'Session closed with error code 2', | ||
| 47 | + .on('error', common.mustCall((err) => { | ||
| 48 | + if (err.code !== 'ECONNRESET') { | ||
| 49 | + assert.strictEqual(err.code, 'ERR_HTTP2_SESSION_ERROR'); | ||
| 50 | + assert.strictEqual(err.message, 'Session closed with error code 2'); | ||
| 51 | + } | ||
| 50 | 52 | })) | |
| 51 | 53 | .on('close', () => { | |
| 52 | 54 | server.removeAllListeners('error'); | |
| 53 | 55 | http2.connect(url) | |
| 54 | - .on('error', common.expectsError({ | ||
| 55 | - code: 'ERR_HTTP2_SESSION_ERROR', | ||
| 56 | - message: 'Session closed with error code 2', | ||
| 57 | - })) | ||
| 56 | + .on('error', common.mustCall((err) => { | ||
| 57 | + if (err.code !== 'ECONNRESET') { | ||
| 58 | + assert.strictEqual(err.code, 'ERR_HTTP2_SESSION_ERROR'); | ||
| 59 | + assert.strictEqual(err.message, 'Session closed with error code 2'); | ||
| 60 | + } | ||
| 61 | + })) | ||
| 58 | 62 | .on('close', () => server.close()); | |
| 59 | 63 | }); | |
| 60 | 64 | })); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -29,9 +29,11 @@ function doTest(session) { | |||
| 29 | 29 | ||
| 30 | 30 | server.listen(0, common.mustCall(() => { | |
| 31 | 31 | const client = h2.connect(`http://localhost:${server.address().port}`); | |
| 32 | - client.on('error', common.expectsError({ | ||
| 33 | - code: 'ERR_HTTP2_SESSION_ERROR', | ||
| 34 | - message: 'Session closed with error code 2', | ||
| 32 | + client.on('error', common.mustCall((err) => { | ||
| 33 | + if (err.code !== 'ECONNRESET') { | ||
| 34 | + assert.strictEqual(err.code, 'ERR_HTTP2_SESSION_ERROR'); | ||
| 35 | + assert.strictEqual(err.message, 'Session closed with error code 2'); | ||
| 36 | + } | ||
| 35 | 37 | })); | |
| 36 | 38 | client.on('close', common.mustCall(() => server.close())); | |
| 37 | 39 | })); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments