Closed
Description
Version
12 / 14 / 16 / 18 and current LTS
Platform
all
Subsystem
vm
What steps will reproduce the bug?
const { Worker, isMainThread } = require('worker_threads');
const vm = require('vm')
if (isMainThread) {
for (let i = 0; i < 2; i++) {
new Worker(__filename);
}
} else {
const ctx = vm.createContext({});
setInterval(() => {
vm.runInContext('console.log(1)', ctx, { breakOnSigint: true })
}, 0)
}
How often does it reproduce? Is there a required condition?
Always
What do you see instead?
node/out/Debug/node[10185]: ../../src/node_watchdog.cc:387:void node::SigintWatchdogHelper::Unregister(node::SigintWatchdogBase *): Assertion `(it) != (watchdogs_.end())' failed.
1: 0x104d4d3c0 node::DumpBacktrace(__sFILE*) [/Users/william/workspace/node/out/Debug/node]
2: 0x104e9fcd0 node::Abort() [/Users/william/workspace/node/out/Debug/node]
3: 0x104e9f8cc node::AppendExceptionLine(node::Environment*, v8::Local<v8::Value>, v8::Local<v8::Message>, node::ErrorHandlingMode) [/Users/william/workspace/node/out/Debug/node]
4: 0x105065c2c node::SigintWatchdogHelper::Unregister(node::SigintWatchdogBase*) [/Users/william/workspace/node/out/Debug/node]
5: 0x105065b70 node::SigintWatchdog::~SigintWatchdog() [/Users/william/workspace/node/out/Debug/node]
6: 0x105065e2c node::SigintWatchdog::~SigintWatchdog() [/Users/william/workspace/node/out/Debug/node]
7: 0x104e731e0 node::contextify::ContextifyScript::EvalMachine(node::Environment*, long long, bool, bool, bool, std::__1::shared_ptr<v8::MicrotaskQueue>, v8::FunctionCallbackInfo<v8::Value> const&) [/Users/william/workspace/node/out/Debug/node]
8: 0x104e72458 node::contextify::ContextifyScript::RunInContext(v8::FunctionCallbackInfo<v8::Value> const&) [/Users/william/workspace/node/out/Debug/node]
9: 0x1053ae410 v8::internal::FunctionCallbackArguments::Call(v8::internal::CallHandlerInfo) [/Users/william/workspace/node/out/Debug/node]
10: 0x1053accc8 v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, v8::internal::BuiltinArguments) [/Users/william/workspace/node/out/Debug/node]
11: 0x1053ab40c v8::internal::Builtin_HandleApiCall(int, unsigned long*, v8::internal::Isolate*) [/Users/william/workspace/node/out/Debug/node]
12: 0x105fec9cc Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_BuiltinExit [/Users/william/workspace/node/out/Debug/node]
13: 0x150057eb4
14: 0x15005a8c8
15: 0x150056a8c
16: 0x1500597b8
17: 0x15005790c
18: 0x105f6feac Builtins_JSEntryTrampoline [/Users/william/workspace/node/out/Debug/node]
19: 0x105f6fb44 Builtins_JSEntry [/Users/william/workspace/node/out/Debug/node]
20: 0x105519570 v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&) [/Users/william/workspace/node/out/Debug/node]
21: 0x10551877c v8::internal::Execution::Call(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*) [/Users/william/workspace/node/out/Debug/node]
22: 0x105300ffc v8::Function::Call(v8::Local<v8::Context>, v8::Local<v8::Value>, int, v8::Local<v8::Value>*) [/Users/william/workspace/node/out/Debug/node]
23: 0x104d7f1b8 node::Environment::RunTimers(uv_timer_s*) [/Users/william/workspace/node/out/Debug/node]
24: 0x105f3c540 uv__run_timers [/Users/william/workspace/node/out/Debug/node]
25: 0x105f43548 uv_run [/Users/william/workspace/node/out/Debug/node]
26: 0x104cd6b78 node::SpinEventLoop(node::Environment*) [/Users/william/workspace/node/out/Debug/node]
27: 0x10506b2b4 node::worker::Worker::Run() [/Users/william/workspace/node/out/Debug/node]
28: 0x105072338 node::worker::Worker::StartThread(v8::FunctionCallbackInfo<v8::Value> const&)::$_3::operator()(void*) const [/Users/william/workspace/node/out/Debug/node]
29: 0x1050722e4 node::worker::Worker::StartThread(v8::FunctionCallbackInfo<v8::Value> const&)::$_3::__invoke(void*) [/Users/william/workspace/node/out/Debug/node]
30: 0x1c0a8826c _pthread_start [/usr/lib/system/libsystem_pthread.dylib]
31: 0x1c0a8308c thread_start [/usr/lib/system/libsystem_pthread.dylib]
[1] 10185 abort node/out/Debug/node index.js
Activity
theanarkh commentedon Jul 6, 2022
I think because modifying the
watchdogs_
andstart_stop_count_
ofSigintWatchdogHelper
is not a atomic operation. And the related code is as follows.The operation as follows will trigger the bug:
Register
andStart
:watchdogs_,size()
is 1 andstart_stop_count_
is 1.Register
:watchdogs_,size()
is 2 andstart_stop_count_
is 1.UnRegister
andStop
: becausestart_stop_count_
is 1, SoSigintWatchdogHelper
will clearwatchdogs_
. Sowatchdogs_.size()
is 0 andstart_stop_count_
is 0.Start
:watchdogs_.size()
is 0 andstart_stop_count_
is 1.UnRegister
: becausewatchdogs_.size()
is 0 soCHECK_NE(it, watchdogs_.end());
is failed.I modify the code to verify this.
It works.
src: fix node watchdog race condition
src: fix node watchdog race condition
src: fix node watchdog race condition
src: fix node watchdog race condition
src: fix node watchdog race condition