Skip to content

Commit 2493655

Browse files
theanarkhdanielleadams
authored andcommitted
src: fix node watchdog race condition
PR-URL: #43780Fixes: #43699 Reviewed-By: Darshan Sen <raisinten@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent fc843e1 commit 2493655

3 files changed

Lines changed: 30 additions & 0 deletions

File tree

‎src/node_watchdog.cc‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ void Watchdog::Timer(uv_timer_t* timer) {
102102
SigintWatchdog::SigintWatchdog(
103103
v8::Isolate* isolate, bool* received_signal)
104104
: isolate_(isolate), received_signal_(received_signal) {
105+
Mutex::ScopedLock lock(SigintWatchdogHelper::GetInstanceActionMutex());
105106
// Register this watchdog with the global SIGINT/Ctrl+C listener.
106107
SigintWatchdogHelper::GetInstance()->Register(this);
107108
// Start the helper thread, if that has not already happened.
@@ -110,6 +111,7 @@ SigintWatchdog::SigintWatchdog(
110111

111112

112113
SigintWatchdog::~SigintWatchdog() {
114+
Mutex::ScopedLock lock(SigintWatchdogHelper::GetInstanceActionMutex());
113115
SigintWatchdogHelper::GetInstance()->Unregister(this);
114116
SigintWatchdogHelper::GetInstance()->Stop();
115117
}
@@ -144,6 +146,7 @@ void TraceSigintWatchdog::New(const FunctionCallbackInfo<Value>& args) {
144146
voidTraceSigintWatchdog::Start(const FunctionCallbackInfo<Value>& args) {
145147
TraceSigintWatchdog* watchdog;
146148
ASSIGN_OR_RETURN_UNWRAP(&watchdog, args.Holder());
149+
Mutex::ScopedLock lock(SigintWatchdogHelper::GetInstanceActionMutex());
147150
// Register this watchdog with the global SIGINT/Ctrl+C listener.
148151
SigintWatchdogHelper::GetInstance()->Register(watchdog);
149152
// Start the helper thread, if that has not already happened.
@@ -154,6 +157,7 @@ void TraceSigintWatchdog::Start(const FunctionCallbackInfo<Value>& args) {
154157
voidTraceSigintWatchdog::Stop(const FunctionCallbackInfo<Value>& args) {
155158
TraceSigintWatchdog* watchdog;
156159
ASSIGN_OR_RETURN_UNWRAP(&watchdog, args.Holder());
160+
Mutex::ScopedLock lock(SigintWatchdogHelper::GetInstanceActionMutex());
157161
SigintWatchdogHelper::GetInstance()->Unregister(watchdog);
158162
SigintWatchdogHelper::GetInstance()->Stop();
159163
}
@@ -215,6 +219,7 @@ void TraceSigintWatchdog::HandleInterrupt() {
215219
signal_flag_ = SignalFlags::None;
216220
interrupting = false;
217221

222+
Mutex::ScopedLock lock(SigintWatchdogHelper::GetInstanceActionMutex());
218223
SigintWatchdogHelper::GetInstance()->Unregister(this);
219224
SigintWatchdogHelper::GetInstance()->Stop();
220225
raise(SIGINT);
@@ -413,6 +418,7 @@ SigintWatchdogHelper::~SigintWatchdogHelper() {
413418
}
414419

415420
SigintWatchdogHelper SigintWatchdogHelper::instance;
421+
Mutex SigintWatchdogHelper::instance_action_mutex_;
416422

417423
namespacewatchdog {
418424
staticvoidInitialize(Local<Object> target,

‎src/node_watchdog.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ class TraceSigintWatchdog : public HandleWrap, public SigintWatchdogBase {
110110
classSigintWatchdogHelper {
111111
public:
112112
static SigintWatchdogHelper* GetInstance() { return &instance; }
113+
static Mutex& GetInstanceActionMutex() { return instance_action_mutex_; }
113114
voidRegister(SigintWatchdogBase* watchdog);
114115
voidUnregister(SigintWatchdogBase* watchdog);
115116
boolHasPendingSignal();
@@ -123,6 +124,7 @@ class SigintWatchdogHelper {
123124

124125
staticboolInformWatchdogsAboutSignal();
125126
static SigintWatchdogHelper instance;
127+
static Mutex instance_action_mutex_;
126128

127129
int start_stop_count_;
128130

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
'use strict';
2+
constcommon=require('../common');
3+
4+
// This test ensures that running vm with breakOnSignt option in multiple
5+
// worker_threads does not crash.
6+
// Issue: https://github.com/nodejs/node/issues/43699
7+
const{ Worker }=require('worker_threads');
8+
constvm=require('vm');
9+
10+
// Don't use isMainThread to allow running this test inside a worker.
11+
if(!process.env.HAS_STARTED_WORKER){
12+
process.env.HAS_STARTED_WORKER=1;
13+
for(leti=0;i<10;i++){
14+
constworker=newWorker(__filename);
15+
worker.on('exit',common.mustCall());
16+
}
17+
}else{
18+
constctx=vm.createContext({});
19+
for(leti=0;i<10000;i++){
20+
vm.runInContext('console.log(1)',ctx,{breakOnSigint: true});
21+
}
22+
}

0 commit comments

Comments
 (0)