src: fix node watchdog race condition
PR-URL: https://github.com/nodejs/node/pull/43780 Fixes: https://github.com/nodejs/node/issues/43699 Reviewed-By: Darshan Sen <raisinten@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
This commit is contained in:
parent
eabd1c2dbc
commit
4917f444e6
@ -102,6 +102,7 @@ void Watchdog::Timer(uv_timer_t* timer) {
|
|||||||
SigintWatchdog::SigintWatchdog(
|
SigintWatchdog::SigintWatchdog(
|
||||||
v8::Isolate* isolate, bool* received_signal)
|
v8::Isolate* isolate, bool* received_signal)
|
||||||
: isolate_(isolate), received_signal_(received_signal) {
|
: isolate_(isolate), received_signal_(received_signal) {
|
||||||
|
Mutex::ScopedLock lock(SigintWatchdogHelper::GetInstanceActionMutex());
|
||||||
// Register this watchdog with the global SIGINT/Ctrl+C listener.
|
// Register this watchdog with the global SIGINT/Ctrl+C listener.
|
||||||
SigintWatchdogHelper::GetInstance()->Register(this);
|
SigintWatchdogHelper::GetInstance()->Register(this);
|
||||||
// Start the helper thread, if that has not already happened.
|
// Start the helper thread, if that has not already happened.
|
||||||
@ -110,6 +111,7 @@ SigintWatchdog::SigintWatchdog(
|
|||||||
|
|
||||||
|
|
||||||
SigintWatchdog::~SigintWatchdog() {
|
SigintWatchdog::~SigintWatchdog() {
|
||||||
|
Mutex::ScopedLock lock(SigintWatchdogHelper::GetInstanceActionMutex());
|
||||||
SigintWatchdogHelper::GetInstance()->Unregister(this);
|
SigintWatchdogHelper::GetInstance()->Unregister(this);
|
||||||
SigintWatchdogHelper::GetInstance()->Stop();
|
SigintWatchdogHelper::GetInstance()->Stop();
|
||||||
}
|
}
|
||||||
@ -144,6 +146,7 @@ void TraceSigintWatchdog::New(const FunctionCallbackInfo<Value>& args) {
|
|||||||
void TraceSigintWatchdog::Start(const FunctionCallbackInfo<Value>& args) {
|
void TraceSigintWatchdog::Start(const FunctionCallbackInfo<Value>& args) {
|
||||||
TraceSigintWatchdog* watchdog;
|
TraceSigintWatchdog* watchdog;
|
||||||
ASSIGN_OR_RETURN_UNWRAP(&watchdog, args.Holder());
|
ASSIGN_OR_RETURN_UNWRAP(&watchdog, args.Holder());
|
||||||
|
Mutex::ScopedLock lock(SigintWatchdogHelper::GetInstanceActionMutex());
|
||||||
// Register this watchdog with the global SIGINT/Ctrl+C listener.
|
// Register this watchdog with the global SIGINT/Ctrl+C listener.
|
||||||
SigintWatchdogHelper::GetInstance()->Register(watchdog);
|
SigintWatchdogHelper::GetInstance()->Register(watchdog);
|
||||||
// Start the helper thread, if that has not already happened.
|
// Start the helper thread, if that has not already happened.
|
||||||
@ -154,6 +157,7 @@ void TraceSigintWatchdog::Start(const FunctionCallbackInfo<Value>& args) {
|
|||||||
void TraceSigintWatchdog::Stop(const FunctionCallbackInfo<Value>& args) {
|
void TraceSigintWatchdog::Stop(const FunctionCallbackInfo<Value>& args) {
|
||||||
TraceSigintWatchdog* watchdog;
|
TraceSigintWatchdog* watchdog;
|
||||||
ASSIGN_OR_RETURN_UNWRAP(&watchdog, args.Holder());
|
ASSIGN_OR_RETURN_UNWRAP(&watchdog, args.Holder());
|
||||||
|
Mutex::ScopedLock lock(SigintWatchdogHelper::GetInstanceActionMutex());
|
||||||
SigintWatchdogHelper::GetInstance()->Unregister(watchdog);
|
SigintWatchdogHelper::GetInstance()->Unregister(watchdog);
|
||||||
SigintWatchdogHelper::GetInstance()->Stop();
|
SigintWatchdogHelper::GetInstance()->Stop();
|
||||||
}
|
}
|
||||||
@ -215,6 +219,7 @@ void TraceSigintWatchdog::HandleInterrupt() {
|
|||||||
signal_flag_ = SignalFlags::None;
|
signal_flag_ = SignalFlags::None;
|
||||||
interrupting = false;
|
interrupting = false;
|
||||||
|
|
||||||
|
Mutex::ScopedLock lock(SigintWatchdogHelper::GetInstanceActionMutex());
|
||||||
SigintWatchdogHelper::GetInstance()->Unregister(this);
|
SigintWatchdogHelper::GetInstance()->Unregister(this);
|
||||||
SigintWatchdogHelper::GetInstance()->Stop();
|
SigintWatchdogHelper::GetInstance()->Stop();
|
||||||
raise(SIGINT);
|
raise(SIGINT);
|
||||||
@ -413,6 +418,7 @@ SigintWatchdogHelper::~SigintWatchdogHelper() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SigintWatchdogHelper SigintWatchdogHelper::instance;
|
SigintWatchdogHelper SigintWatchdogHelper::instance;
|
||||||
|
Mutex SigintWatchdogHelper::instance_action_mutex_;
|
||||||
|
|
||||||
namespace watchdog {
|
namespace watchdog {
|
||||||
static void Initialize(Local<Object> target,
|
static void Initialize(Local<Object> target,
|
||||||
|
@ -110,6 +110,7 @@ class TraceSigintWatchdog : public HandleWrap, public SigintWatchdogBase {
|
|||||||
class SigintWatchdogHelper {
|
class SigintWatchdogHelper {
|
||||||
public:
|
public:
|
||||||
static SigintWatchdogHelper* GetInstance() { return &instance; }
|
static SigintWatchdogHelper* GetInstance() { return &instance; }
|
||||||
|
static Mutex& GetInstanceActionMutex() { return instance_action_mutex_; }
|
||||||
void Register(SigintWatchdogBase* watchdog);
|
void Register(SigintWatchdogBase* watchdog);
|
||||||
void Unregister(SigintWatchdogBase* watchdog);
|
void Unregister(SigintWatchdogBase* watchdog);
|
||||||
bool HasPendingSignal();
|
bool HasPendingSignal();
|
||||||
@ -123,6 +124,7 @@ class SigintWatchdogHelper {
|
|||||||
|
|
||||||
static bool InformWatchdogsAboutSignal();
|
static bool InformWatchdogsAboutSignal();
|
||||||
static SigintWatchdogHelper instance;
|
static SigintWatchdogHelper instance;
|
||||||
|
static Mutex instance_action_mutex_;
|
||||||
|
|
||||||
int start_stop_count_;
|
int start_stop_count_;
|
||||||
|
|
||||||
|
22
test/parallel/test-vm-break-on-sigint.js
Normal file
22
test/parallel/test-vm-break-on-sigint.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
'use strict';
|
||||||
|
const common = require('../common');
|
||||||
|
|
||||||
|
// This test ensures that running vm with breakOnSignt option in multiple
|
||||||
|
// worker_threads does not crash.
|
||||||
|
// Issue: https://github.com/nodejs/node/issues/43699
|
||||||
|
const { Worker } = require('worker_threads');
|
||||||
|
const vm = require('vm');
|
||||||
|
|
||||||
|
// Don't use isMainThread to allow running this test inside a worker.
|
||||||
|
if (!process.env.HAS_STARTED_WORKER) {
|
||||||
|
process.env.HAS_STARTED_WORKER = 1;
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
const worker = new Worker(__filename);
|
||||||
|
worker.on('exit', common.mustCall());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const ctx = vm.createContext({});
|
||||||
|
for (let i = 0; i < 10000; i++) {
|
||||||
|
vm.runInContext('console.log(1)', ctx, { breakOnSigint: true });
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user