Skip to content

Instantly share code, notes, and snippets.

@trevnorris
Created October 25, 2016 21:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trevnorris/0e130c6c8f0aa1336725e8e41c38cf14 to your computer and use it in GitHub Desktop.
Save trevnorris/0e130c6c8f0aa1336725e8e41c38cf14 to your computer and use it in GitHub Desktop.
Fix when the reference of a TLSWrap instance is kept, but the StreamBase stream_ is free'd.
diff --git a/src/stream_base.h b/src/stream_base.h
index faddee8..3592975 100644
--- a/src/stream_base.h
+++ b/src/stream_base.h
@@ -146,10 +146,14 @@ class StreamResource {
const uv_buf_t* buf,
uv_handle_type pending,
void* ctx);
+ typedef void (*DestructCb)(void* ctx);
StreamResource() : bytes_read_(0) {
}
- virtual ~StreamResource() = default;
+ virtual ~StreamResource() {
+ if (!destruct_cb_.is_empty())
+ destruct_cb_.fn(destruct_cb_.ctx);
+ }
virtual int DoShutdown(ShutdownWrap* req_wrap) = 0;
virtual int DoTryWrite(uv_buf_t** bufs, size_t* count);
@@ -186,15 +190,18 @@ class StreamResource {
inline void set_alloc_cb(Callback<AllocCb> c) { alloc_cb_ = c; }
inline void set_read_cb(Callback<ReadCb> c) { read_cb_ = c; }
+ inline void set_destruct_cb(Callback<DestructCb> c) { destruct_cb_ = c; }
inline Callback<AfterWriteCb> after_write_cb() { return after_write_cb_; }
inline Callback<AllocCb> alloc_cb() { return alloc_cb_; }
inline Callback<ReadCb> read_cb() { return read_cb_; }
+ inline Callback<DestructCb> destruct_cb() { return destruct_cb_; }
private:
Callback<AfterWriteCb> after_write_cb_;
Callback<AllocCb> alloc_cb_;
Callback<ReadCb> read_cb_;
+ Callback<DestructCb> destruct_cb_;
uint64_t bytes_read_;
friend class StreamBase;
diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc
index d1b1aec..39642cf 100644
--- a/src/tls_wrap.cc
+++ b/src/tls_wrap.cc
@@ -64,6 +64,7 @@ TLSWrap::TLSWrap(Environment* env,
stream_->set_after_write_cb({ OnAfterWriteImpl, this });
stream_->set_alloc_cb({ OnAllocImpl, this });
stream_->set_read_cb({ OnReadImpl, this });
+ stream_->set_destruct_cb({ OnDestructImpl, this });
set_alloc_cb({ OnAllocSelf, this });
set_read_cb({ OnReadSelf, this });
@@ -522,7 +523,7 @@ int TLSWrap::GetFD() {
bool TLSWrap::IsAlive() {
- return ssl_ != nullptr && stream_->IsAlive();
+ return ssl_ != nullptr && stream_ != nullptr && stream_->IsAlive();
}
@@ -660,6 +661,12 @@ void TLSWrap::OnReadImpl(ssize_t nread,
}
+void TLSWrap::OnDestructImpl(void* ctx) {
+ TLSWrap* wrap = static_cast<TLSWrap*>(ctx);
+ wrap->clear_stream();
+}
+
+
void TLSWrap::OnAllocSelf(size_t suggested_size, uv_buf_t* buf, void* ctx) {
buf->base = static_cast<char*>(node::Malloc(suggested_size));
CHECK_NE(buf->base, nullptr);
diff --git a/src/tls_wrap.h b/src/tls_wrap.h
index f390c9f..fbf664e 100644
--- a/src/tls_wrap.h
+++ b/src/tls_wrap.h
@@ -54,6 +54,8 @@ class TLSWrap : public AsyncWrap,
size_t self_size() const override { return sizeof(*this); }
+ void clear_stream() { stream_ = nullptr; }
+
protected:
static const int kClearOutChunkSize = 16384;
@@ -121,6 +123,7 @@ class TLSWrap : public AsyncWrap,
const uv_buf_t* buf,
uv_handle_type pending,
void* ctx);
+ static void OnDestructImpl(void* ctx);
void DoRead(ssize_t nread, const uv_buf_t* buf, uv_handle_type pending);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment