node/test/parallel/test-util-sigint-watchdog.js
Anna Henningsen 0815b9401d
vm: add ability to break on sigint/ctrl+c
- Adds the `breakEvalOnSigint` option to `vm.runIn(This)Context`.
  This uses a watchdog thread to wait for SIGINT and generally works
  just like the existing `timeout` option.

- Adds a method to the existing timer-based watchdog to check if it
  stopped regularly or by running into the timeout. This is used to
  tell a SIGINT abort from a timer-based one.

- Adds (internal) `process._{start,stop}SigintWatchdog` methods to
  start/stop the watchdog thread used by the above option manually.
  This will be used in the REPL to set up SIGINT handling before
  entering terminal raw mode, so that there is no time window in
  which Ctrl+C fully aborts the process.

PR-URL: https://github.com/nodejs/node/pull/6635
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
2016-06-18 20:44:16 +02:00

54 lines
1.7 KiB
JavaScript

'use strict';
const common = require('../common');
const assert = require('assert');
const binding = process.binding('util');
if (process.platform === 'win32') {
// No way to send CTRL_C_EVENT to processes from JS right now.
common.skip('platform not supported');
return;
}
[(next) => {
// Test with no signal observed.
binding.startSigintWatchdog();
const hadPendingSignals = binding.stopSigintWatchdog();
assert.strictEqual(hadPendingSignals, false);
next();
},
(next) => {
// Test with one call to the watchdog, one signal.
binding.startSigintWatchdog();
process.kill(process.pid, 'SIGINT');
setTimeout(common.mustCall(() => {
const hadPendingSignals = binding.stopSigintWatchdog();
assert.strictEqual(hadPendingSignals, true);
next();
}), common.platformTimeout(100));
},
(next) => {
// Nested calls are okay.
binding.startSigintWatchdog();
binding.startSigintWatchdog();
process.kill(process.pid, 'SIGINT');
setTimeout(common.mustCall(() => {
const hadPendingSignals1 = binding.stopSigintWatchdog();
const hadPendingSignals2 = binding.stopSigintWatchdog();
assert.strictEqual(hadPendingSignals1, true);
assert.strictEqual(hadPendingSignals2, false);
next();
}), common.platformTimeout(100));
},
() => {
// Signal comes in after first call to stop.
binding.startSigintWatchdog();
binding.startSigintWatchdog();
const hadPendingSignals1 = binding.stopSigintWatchdog();
process.kill(process.pid, 'SIGINT');
setTimeout(common.mustCall(() => {
const hadPendingSignals2 = binding.stopSigintWatchdog();
assert.strictEqual(hadPendingSignals1, false);
assert.strictEqual(hadPendingSignals2, true);
}), common.platformTimeout(100));
}].reduceRight((a, b) => common.mustCall(b).bind(null, a))();