From 4c9db6c74150d3f5487798ca654496fdaf343422 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 26 Nov 2019 17:08:11 +0100 Subject: [PATCH] src: no SetImmediate from destructor in stream_pipe code Guard against running `SetImmediate()` from the destructor. The object will not be alive or usable in the callback, so it does not make sense to attempt to schedule the `SetImmediate()`. PR-URL: https://github.com/nodejs/node/pull/30666 Fixes: https://github.com/nodejs/node/issues/30643 Refs: https://github.com/nodejs/node/pull/30374 Reviewed-By: Rich Trott Reviewed-By: James M Snell --- src/stream_pipe.cc | 6 ++++-- src/stream_pipe.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/stream_pipe.cc b/src/stream_pipe.cc index b84c8f4c663422..d405c4d5cbeaed 100644 --- a/src/stream_pipe.cc +++ b/src/stream_pipe.cc @@ -42,7 +42,7 @@ StreamPipe::StreamPipe(StreamBase* source, } StreamPipe::~StreamPipe() { - Unpipe(); + Unpipe(true); } StreamBase* StreamPipe::source() { @@ -53,7 +53,7 @@ StreamBase* StreamPipe::sink() { return static_cast(writable_listener_.stream()); } -void StreamPipe::Unpipe() { +void StreamPipe::Unpipe(bool is_in_deletion) { if (is_closed_) return; @@ -68,6 +68,8 @@ void StreamPipe::Unpipe() { source()->RemoveStreamListener(&readable_listener_); sink()->RemoveStreamListener(&writable_listener_); + if (is_in_deletion) return; + // Delay the JS-facing part with SetImmediate, because this might be from // inside the garbage collector, so we can’t run JS here. HandleScope handle_scope(env()->isolate()); diff --git a/src/stream_pipe.h b/src/stream_pipe.h index 061ad9842e8f6d..0e155006102eaa 100644 --- a/src/stream_pipe.h +++ b/src/stream_pipe.h @@ -12,7 +12,7 @@ class StreamPipe : public AsyncWrap { StreamPipe(StreamBase* source, StreamBase* sink, v8::Local obj); ~StreamPipe() override; - void Unpipe(); + void Unpipe(bool is_in_deletion = false); static void New(const v8::FunctionCallbackInfo& args); static void Start(const v8::FunctionCallbackInfo& args);