From eb8beb5f5f9492d18082cb5c34d56b1e40831188 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Sat, 2 Nov 2019 18:58:24 +0100 Subject: [PATCH] src: track no of active JS signal handlers This makes it possible to tell whether a signal is being tracked in JS. PR-URL: https://github.com/nodejs/node/pull/30229 Reviewed-By: Colin Ihrig Reviewed-By: Gireesh Punathil Reviewed-By: Joyee Cheung Reviewed-By: Shelley Vohr --- src/node_internals.h | 2 ++ src/signal_wrap.cc | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/node_internals.h b/src/node_internals.h index 52f7f5d503f739..050e9a5c46ff90 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -314,6 +314,8 @@ void EndStartedProfilers(Environment* env); } #endif // HAVE_INSPECTOR +bool HasSignalJSHandler(int signum); + #ifdef _WIN32 typedef SYSTEMTIME TIME_TYPE; #else // UNIX, OSX diff --git a/src/signal_wrap.cc b/src/signal_wrap.cc index 90b91f35a86c8b..cf67dc590f6d51 100644 --- a/src/signal_wrap.cc +++ b/src/signal_wrap.cc @@ -38,8 +38,13 @@ using v8::Object; using v8::String; using v8::Value; +void DecreaseSignalHandlerCount(int signum); + namespace { +static Mutex handled_signals_mutex; +static std::map handled_signals; // Signal -> number of handlers + class SignalWrap : public HandleWrap { public: static void Initialize(Local target, @@ -85,6 +90,11 @@ class SignalWrap : public HandleWrap { CHECK_EQ(r, 0); } + void Close(v8::Local close_callback) override { + if (active_) DecreaseSignalHandlerCount(handle_.signum); + HandleWrap::Close(close_callback); + } + static void Start(const FunctionCallbackInfo& args) { SignalWrap* wrap; ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); @@ -112,21 +122,49 @@ class SignalWrap : public HandleWrap { wrap->MakeCallback(env->onsignal_string(), 1, &arg); }, signum); + + if (err == 0) { + CHECK(!wrap->active_); + wrap->active_ = true; + Mutex::ScopedLock lock(handled_signals_mutex); + handled_signals[signum]++; + } + args.GetReturnValue().Set(err); } static void Stop(const FunctionCallbackInfo& args) { SignalWrap* wrap; ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); + + if (wrap->active_) { + wrap->active_ = false; + DecreaseSignalHandlerCount(wrap->handle_.signum); + } + int err = uv_signal_stop(&wrap->handle_); args.GetReturnValue().Set(err); } uv_signal_t handle_; + bool active_ = false; }; } // anonymous namespace + +void DecreaseSignalHandlerCount(int signum) { + Mutex::ScopedLock lock(handled_signals_mutex); + int new_handler_count = --handled_signals[signum]; + CHECK_GE(new_handler_count, 0); + if (new_handler_count == 0) + handled_signals.erase(signum); +} + +bool HasSignalJSHandler(int signum) { + Mutex::ScopedLock lock(handled_signals_mutex); + return handled_signals.find(signum) != handled_signals.end(); +} } // namespace node