-
-
Notifications
You must be signed in to change notification settings - Fork 33.5k
Closed
Labels
http2Issues or PRs related to the http2 subsystem.Issues or PRs related to the http2 subsystem.tlsIssues and PRs related to the tls subsystem.Issues and PRs related to the tls subsystem.
Description
node: v8.11.3
system: Ubuntu 18.04
I am hitting an issue with nodejs v8.11.3. I am using http2 with TLS (https) and the server aborts when the client has closed the session. Here is the error:
HTTP2 31334: Http2Session server: socket closed
HTTP2 31334: Http2Session server: marking session closed
HTTP2 31334: Http2Session server: submitting goaway
node[31334]: ../src/tls_wrap.cc:604:virtual int node::TLSWrap::DoWrite(node::WriteWrap*, uv_buf_t*, size_t, uv_stream_t*): Assertion `(ssl_) != (nullptr)' failed.
1: node::Abort() [node]
2: 0x8c25db [node]
3: node::TLSWrap::DoWrite(node::WriteWrap*, uv_buf_t*, unsigned long, uv_stream_s*) [node]
4: node::http2::Http2Session::SendPendingData() [node]
5: 0x90e769 [node]
6: node::Environment::RunAndClearNativeImmediates() [node]
7: node::Environment::CheckImmediate(uv_check_s*) [node]
8: 0x141a4ac [node]
9: uv_run [node]
10: node::Start(uv_loop_s*, int, char const* const*, int, char const* const*) [node]
11: node::Start(int, char**) [node]
12: __libc_start_main [/lib/x86_64-linux-gnu/libc.so.6]
13: 0x89b1b1 [node]
Aborted (core dumped)
What confuses me is why does the server still emit a GOAWAY frame although the socket already was closed?
Note: the problem does not always happen, but is reproducible as part of a more complex test scenario.
QUIRK SOLUTION
I made a quirk to circumvent the problem by monkeypatching "goaway" and introduction an explicit check if the socket has been closed. TypeScript code:
const GOAWAY = Symbol();
interface ExtServerHttp2Session extends http2.ServerHttp2Session {
[GOAWAY]?: (code?: number, lastStreamID?: number, opaqueData?: Buffer | DataView /*| TypedArray*/) => void;
}
function patchedGoaway(
this: ExtServerHttp2Session,
code?: number,
lastStreamID?: number,
opaqueData?: Buffer | DataView /*| TypedArray*/
): void {
if (!this.closed) {
this[GOAWAY]!(code, lastStreamID, opaqueData);
}
}
function monkeyPatch(session: http2.Http2Session) {
const extSession = session as ExtServerHttp2Session;
if (!extSession[GOAWAY]) {
extSession[GOAWAY] = extSession.goaway;
extSession.goaway = patchedGoaway;
}
}
Now when handling a new stream, you call monkeyPatch(stream.session).
Metadata
Metadata
Assignees
Labels
http2Issues or PRs related to the http2 subsystem.Issues or PRs related to the http2 subsystem.tlsIssues and PRs related to the tls subsystem.Issues and PRs related to the tls subsystem.