Browse Source

test,util: fix flaky test-util-sigint-watchdog

Fix parallel/test-util-sigint-watchdog by polling until the
signal has definitely been received instead of just using a timeout.

Fixes: https://github.com/nodejs/node/issues/7919
PR-URL: https://github.com/nodejs/node/pull/7933
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
v6.x
Anna Henningsen 9 years ago
committed by cjihrig
parent
commit
4416ffab8a
  1. 8
      src/node_util.cc
  2. 7
      src/node_watchdog.cc
  3. 1
      src/node_watchdog.h
  4. 19
      test/parallel/test-util-sigint-watchdog.js

8
src/node_util.cc

@ -103,6 +103,13 @@ void StopSigintWatchdog(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(had_pending_signals); args.GetReturnValue().Set(had_pending_signals);
} }
void WatchdogHasPendingSigint(const FunctionCallbackInfo<Value>& args) {
bool ret = SigintWatchdogHelper::GetInstance()->HasPendingSignal();
args.GetReturnValue().Set(ret);
}
void Initialize(Local<Object> target, void Initialize(Local<Object> target,
Local<Value> unused, Local<Value> unused,
Local<Context> context) { Local<Context> context) {
@ -118,6 +125,7 @@ void Initialize(Local<Object> target,
env->SetMethod(target, "startSigintWatchdog", StartSigintWatchdog); env->SetMethod(target, "startSigintWatchdog", StartSigintWatchdog);
env->SetMethod(target, "stopSigintWatchdog", StopSigintWatchdog); env->SetMethod(target, "stopSigintWatchdog", StopSigintWatchdog);
env->SetMethod(target, "watchdogHasPendingSigint", WatchdogHasPendingSigint);
} }
} // namespace util } // namespace util

7
src/node_watchdog.cc

@ -258,6 +258,13 @@ bool SigintWatchdogHelper::Stop() {
} }
bool SigintWatchdogHelper::HasPendingSignal() {
Mutex::ScopedLock lock(list_mutex_);
return has_pending_signal_;
}
void SigintWatchdogHelper::Register(SigintWatchdog* wd) { void SigintWatchdogHelper::Register(SigintWatchdog* wd) {
Mutex::ScopedLock lock(list_mutex_); Mutex::ScopedLock lock(list_mutex_);

1
src/node_watchdog.h

@ -63,6 +63,7 @@ class SigintWatchdogHelper {
static SigintWatchdogHelper* GetInstance() { return &instance; } static SigintWatchdogHelper* GetInstance() { return &instance; }
void Register(SigintWatchdog* watchdog); void Register(SigintWatchdog* watchdog);
void Unregister(SigintWatchdog* watchdog); void Unregister(SigintWatchdog* watchdog);
bool HasPendingSignal();
int Start(); int Start();
bool Stop(); bool Stop();

19
test/parallel/test-util-sigint-watchdog.js

@ -20,24 +20,24 @@ if (common.isWindows) {
// Test with one call to the watchdog, one signal. // Test with one call to the watchdog, one signal.
binding.startSigintWatchdog(); binding.startSigintWatchdog();
process.kill(process.pid, 'SIGINT'); process.kill(process.pid, 'SIGINT');
setTimeout(common.mustCall(() => { waitForPendingSignal(common.mustCall(() => {
const hadPendingSignals = binding.stopSigintWatchdog(); const hadPendingSignals = binding.stopSigintWatchdog();
assert.strictEqual(hadPendingSignals, true); assert.strictEqual(hadPendingSignals, true);
next(); next();
}), common.platformTimeout(100)); }));
}, },
(next) => { (next) => {
// Nested calls are okay. // Nested calls are okay.
binding.startSigintWatchdog(); binding.startSigintWatchdog();
binding.startSigintWatchdog(); binding.startSigintWatchdog();
process.kill(process.pid, 'SIGINT'); process.kill(process.pid, 'SIGINT');
setTimeout(common.mustCall(() => { waitForPendingSignal(common.mustCall(() => {
const hadPendingSignals1 = binding.stopSigintWatchdog(); const hadPendingSignals1 = binding.stopSigintWatchdog();
const hadPendingSignals2 = binding.stopSigintWatchdog(); const hadPendingSignals2 = binding.stopSigintWatchdog();
assert.strictEqual(hadPendingSignals1, true); assert.strictEqual(hadPendingSignals1, true);
assert.strictEqual(hadPendingSignals2, false); assert.strictEqual(hadPendingSignals2, false);
next(); next();
}), common.platformTimeout(100)); }));
}, },
() => { () => {
// Signal comes in after first call to stop. // Signal comes in after first call to stop.
@ -45,9 +45,16 @@ if (common.isWindows) {
binding.startSigintWatchdog(); binding.startSigintWatchdog();
const hadPendingSignals1 = binding.stopSigintWatchdog(); const hadPendingSignals1 = binding.stopSigintWatchdog();
process.kill(process.pid, 'SIGINT'); process.kill(process.pid, 'SIGINT');
setTimeout(common.mustCall(() => { waitForPendingSignal(common.mustCall(() => {
const hadPendingSignals2 = binding.stopSigintWatchdog(); const hadPendingSignals2 = binding.stopSigintWatchdog();
assert.strictEqual(hadPendingSignals1, false); assert.strictEqual(hadPendingSignals1, false);
assert.strictEqual(hadPendingSignals2, true); assert.strictEqual(hadPendingSignals2, true);
}), common.platformTimeout(100)); }));
}].reduceRight((a, b) => common.mustCall(b).bind(null, a))(); }].reduceRight((a, b) => common.mustCall(b).bind(null, a))();
function waitForPendingSignal(cb) {
if (binding.watchdogHasPendingSigint())
cb();
else
setTimeout(waitForPendingSignal, 10, cb);
}

Loading…
Cancel
Save