From 16cac51b3b1eb5a6b1366cad65601b0f5920d40c Mon Sep 17 00:00:00 2001 From: theanarkh Date: Sat, 16 Mar 2024 02:48:23 +0800 Subject: [PATCH] src: make start of signal_wrap reenterable --- src/signal_wrap.cc | 7 ++++++- test/parallel/test-signal-reuse.js | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-signal-reuse.js diff --git a/src/signal_wrap.cc b/src/signal_wrap.cc index 14132caab9b269..844a42a0a57c63 100644 --- a/src/signal_wrap.cc +++ b/src/signal_wrap.cc @@ -118,6 +118,8 @@ class SignalWrap : public HandleWrap { } } #endif + // Save the old signum + int old_signum = wrap->handle_.signum; int err = uv_signal_start( &wrap->handle_, [](uv_signal_t* handle, int signum) { @@ -131,7 +133,10 @@ class SignalWrap : public HandleWrap { signum); if (err == 0) { - CHECK(!wrap->active_); + // Subtract 1 if previously registered + if (wrap->active_) { + DecreaseSignalHandlerCount(old_signum); + } wrap->active_ = true; Mutex::ScopedLock lock(handled_signals_mutex); handled_signals[signum]++; diff --git a/test/parallel/test-signal-reuse.js b/test/parallel/test-signal-reuse.js new file mode 100644 index 00000000000000..477bd4217f6f17 --- /dev/null +++ b/test/parallel/test-signal-reuse.js @@ -0,0 +1,21 @@ +// Flags: --expose-internals +'use strict'; +const common = require('../common'); +const { internalBinding } = require('internal/test/binding'); +const { signals } = internalBinding('constants').os; +const Signal = internalBinding('signal_wrap').Signal; + +common.skipIfWorker(); + +const signal = new Signal(); +signal.start(signals.SIGUSR2); +signal.onsignal = common.mustCall(() => { + process.nextTick(common.mustCall(() => { + signal.start(signals.SIGINT); + signal.onsignal = common.mustCall(() => { + signal.close(); + }); + process.kill(0, signals.SIGINT); + })); +}); +process.kill(0, signals.SIGUSR2);