Skip to content

Commit 2493655

Browse files
theanarkhdanielleadams
authored andcommitted
src: fix node watchdog race condition
PR-URL: #43780 Fixes: #43699 Reviewed-By: Darshan Sen <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]>
1 parent fc843e1 commit 2493655

File tree

3 files changed

+30
-0
lines changed

3 files changed

+30
-0
lines changed

src/node_watchdog.cc

+6
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
void TraceSigintWatchdog::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
void TraceSigintWatchdog::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
namespace watchdog {
418424
static void Initialize(Local<Object> target,

src/node_watchdog.h

+2
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ class TraceSigintWatchdog : public HandleWrap, public SigintWatchdogBase {
110110
class SigintWatchdogHelper {
111111
public:
112112
static SigintWatchdogHelper* GetInstance() { return &instance; }
113+
static Mutex& GetInstanceActionMutex() { return instance_action_mutex_; }
113114
void Register(SigintWatchdogBase* watchdog);
114115
void Unregister(SigintWatchdogBase* watchdog);
115116
bool HasPendingSignal();
@@ -123,6 +124,7 @@ class SigintWatchdogHelper {
123124

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

127129
int start_stop_count_;
128130

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
'use strict';
2+
const common = 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+
const vm = 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 (let i = 0; i < 10; i++) {
14+
const worker = new Worker(__filename);
15+
worker.on('exit', common.mustCall());
16+
}
17+
} else {
18+
const ctx = vm.createContext({});
19+
for (let i = 0; i < 10000; i++) {
20+
vm.runInContext('console.log(1)', ctx, { breakOnSigint: true });
21+
}
22+
}

0 commit comments

Comments
 (0)