Skip to content

Commit

Permalink
http2: keep session objects alive during Http2Scope
Browse files Browse the repository at this point in the history
Keep a local handle as a reference to the JS `Http2Session`
object so that it will not be garbage collected
when inside an `Http2Scope`, because the presence of the
latter usually indicates that further actions on
the session object are expected.

Strictly speaking, storing the `session_handle_` as a
property on the scope object is not necessary, but
this is not very costly and makes the code more
obviously correct.

Fixes: #17840

Backport-PR-URL: #18050
PR-URL: #17863
Fixes: #17840
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
  • Loading branch information
addaleax authored and MylesBorins committed Jan 10, 2018
1 parent e3c567f commit b8deb75
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/node_http2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ Http2Scope::Http2Scope(Http2Session* session) {
}
session->flags_ |= SESSION_STATE_HAS_SCOPE;
session_ = session;

// Always keep the session object alive for at least as long as
// this scope is active.
session_handle_ = session->object();
CHECK(!session_handle_.IsEmpty());
}

Http2Scope::~Http2Scope() {
Expand Down Expand Up @@ -512,6 +517,7 @@ void Http2Session::Unconsume() {
}

Http2Session::~Http2Session() {
CHECK_EQ(flags_ & SESSION_STATE_HAS_SCOPE, 0);
if (!object().IsEmpty())
ClearWrap(object());
persistent().Reset();
Expand Down Expand Up @@ -1365,6 +1371,7 @@ void Http2Session::OnStreamReadImpl(ssize_t nread,
void* ctx) {
Http2Session* session = static_cast<Http2Session*>(ctx);
Http2Scope h2scope(session);
CHECK_NE(session->stream_, nullptr);
DEBUG_HTTP2SESSION2(session, "receiving %d bytes", nread);
if (nread < 0) {
uv_buf_t tmp_buf;
Expand Down
1 change: 1 addition & 0 deletions src/node_http2.h
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ class Http2Scope {

private:
Http2Session* session_ = nullptr;
Local<Object> session_handle_;
};

// The Http2Options class is used to parse the options object passed in to
Expand Down
11 changes: 11 additions & 0 deletions test/parallel/test-http2-createwritereq.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

// Flags: --expose-gc

const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');
Expand Down Expand Up @@ -62,6 +64,15 @@ server.listen(0, common.mustCall(function() {
}
}));

// Ref: https://github.com/nodejs/node/issues/17840
const origDestroy = req.destroy;
req.destroy = function(...args) {
// Schedule a garbage collection event at the end of the current
// MakeCallback() run.
process.nextTick(global.gc);
return origDestroy.call(this, ...args);
};

req.end();
});
}));

0 comments on commit b8deb75

Please sign in to comment.