http2: make sessions garbage-collectible
Use weak handles to track the lifetime of an `Http2Session` instance. Refs: https://github.com/nodejs/http2/issues/140 PR-URL: https://github.com/nodejs/node/pull/16461 Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
This commit is contained in:
parent
3ddd151611
commit
c8a00fdf62
@ -75,7 +75,7 @@ Http2Session::Http2Session(Environment* env,
|
|||||||
nghttp2_session_type type)
|
nghttp2_session_type type)
|
||||||
: AsyncWrap(env, wrap, AsyncWrap::PROVIDER_HTTP2SESSION),
|
: AsyncWrap(env, wrap, AsyncWrap::PROVIDER_HTTP2SESSION),
|
||||||
StreamBase(env) {
|
StreamBase(env) {
|
||||||
Wrap(object(), this);
|
MakeWeak<Http2Session>(this);
|
||||||
|
|
||||||
Http2Options opts(env);
|
Http2Options opts(env);
|
||||||
|
|
||||||
@ -102,11 +102,16 @@ Http2Session::Http2Session(Environment* env,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Http2Session::~Http2Session() {
|
Http2Session::~Http2Session() {
|
||||||
CHECK_EQ(false, persistent().IsEmpty());
|
CHECK(persistent().IsEmpty());
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Http2Session::Close() {
|
||||||
|
if (!object().IsEmpty())
|
||||||
ClearWrap(object());
|
ClearWrap(object());
|
||||||
persistent().Reset();
|
persistent().Reset();
|
||||||
CHECK_EQ(true, persistent().IsEmpty());
|
|
||||||
|
|
||||||
|
this->Nghttp2Session::Close();
|
||||||
// Stop the loop
|
// Stop the loop
|
||||||
CHECK_EQ(uv_prepare_stop(prep_), 0);
|
CHECK_EQ(uv_prepare_stop(prep_), 0);
|
||||||
auto prep_close = [](uv_handle_t* handle) {
|
auto prep_close = [](uv_handle_t* handle) {
|
||||||
@ -407,7 +412,7 @@ void Http2Session::Destroy(const FunctionCallbackInfo<Value>& args) {
|
|||||||
|
|
||||||
if (!skipUnconsume)
|
if (!skipUnconsume)
|
||||||
session->Unconsume();
|
session->Unconsume();
|
||||||
session->Free();
|
session->Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Http2Session::Destroying(const FunctionCallbackInfo<Value>& args) {
|
void Http2Session::Destroying(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
@ -474,6 +474,8 @@ class Http2Session : public AsyncWrap,
|
|||||||
return stream_buf_;
|
return stream_buf_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Close() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StreamBase* stream_;
|
StreamBase* stream_;
|
||||||
StreamResource::Callback<StreamResource::AllocCb> prev_alloc_cb_;
|
StreamResource::Callback<StreamResource::AllocCb> prev_alloc_cb_;
|
||||||
|
@ -587,16 +587,18 @@ inline void Nghttp2Session::MarkDestroying() {
|
|||||||
destroying_ = true;
|
destroying_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int Nghttp2Session::Free() {
|
inline Nghttp2Session::~Nghttp2Session() {
|
||||||
#if defined(DEBUG) && DEBUG
|
Close();
|
||||||
CHECK(session_ != nullptr);
|
}
|
||||||
#endif
|
|
||||||
|
inline void Nghttp2Session::Close() {
|
||||||
|
if (IsClosed())
|
||||||
|
return;
|
||||||
DEBUG_HTTP2("Nghttp2Session %s: freeing session\n", TypeName());
|
DEBUG_HTTP2("Nghttp2Session %s: freeing session\n", TypeName());
|
||||||
nghttp2_session_terminate_session(session_, NGHTTP2_NO_ERROR);
|
nghttp2_session_terminate_session(session_, NGHTTP2_NO_ERROR);
|
||||||
nghttp2_session_del(session_);
|
nghttp2_session_del(session_);
|
||||||
session_ = nullptr;
|
session_ = nullptr;
|
||||||
DEBUG_HTTP2("Nghttp2Session %s: session freed\n", TypeName());
|
DEBUG_HTTP2("Nghttp2Session %s: session freed\n", TypeName());
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write data received from the socket to the underlying nghttp2_session.
|
// Write data received from the socket to the underlying nghttp2_session.
|
||||||
|
@ -97,7 +97,7 @@ class Nghttp2Session {
|
|||||||
nghttp2_mem* mem = nullptr);
|
nghttp2_mem* mem = nullptr);
|
||||||
|
|
||||||
// Frees this session instance
|
// Frees this session instance
|
||||||
inline int Free();
|
inline ~Nghttp2Session();
|
||||||
inline void MarkDestroying();
|
inline void MarkDestroying();
|
||||||
bool IsDestroying() {
|
bool IsDestroying() {
|
||||||
return destroying_;
|
return destroying_;
|
||||||
@ -140,6 +140,8 @@ class Nghttp2Session {
|
|||||||
// Returns the nghttp2 library session
|
// Returns the nghttp2 library session
|
||||||
inline nghttp2_session* session() const { return session_; }
|
inline nghttp2_session* session() const { return session_; }
|
||||||
|
|
||||||
|
inline bool IsClosed() const { return session_ == nullptr; }
|
||||||
|
|
||||||
nghttp2_session_type type() const {
|
nghttp2_session_type type() const {
|
||||||
return session_type_;
|
return session_type_;
|
||||||
}
|
}
|
||||||
@ -201,6 +203,8 @@ class Nghttp2Session {
|
|||||||
|
|
||||||
virtual uv_loop_t* event_loop() const = 0;
|
virtual uv_loop_t* event_loop() const = 0;
|
||||||
|
|
||||||
|
virtual void Close();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline void HandleHeadersFrame(const nghttp2_frame* frame);
|
inline void HandleHeadersFrame(const nghttp2_frame* frame);
|
||||||
inline void HandlePriorityFrame(const nghttp2_frame* frame);
|
inline void HandlePriorityFrame(const nghttp2_frame* frame);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user