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 <raisinten@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
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

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
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

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
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

Lines changed: 22 additions & 0 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy