• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2const common = require('../common');
3if (common.isWindows) {
4  // No way to send CTRL_C_EVENT to processes from JS right now.
5  common.skip('platform not supported');
6}
7
8const assert = require('assert');
9const vm = require('vm');
10const spawn = require('child_process').spawn;
11
12const methods = [
13  'runInThisContext',
14  'runInContext',
15];
16
17if (process.argv[2] === 'child') {
18  const method = process.argv[3];
19  assert.ok(method);
20
21  let firstHandlerCalled = 0;
22  process.on('SIGINT', common.mustCall(() => {
23    firstHandlerCalled++;
24    // Handler attached _before_ execution.
25  }, 2));
26
27  let onceHandlerCalled = 0;
28  process.once('SIGINT', common.mustCall(() => {
29    onceHandlerCalled++;
30    // Handler attached _before_ execution.
31  }));
32
33  const script = `process.send('${method}'); while(true) {}`;
34  const args = method === 'runInContext' ?
35    [vm.createContext({ process })] :
36    [];
37  const options = { breakOnSigint: true };
38
39  assert.throws(
40    () => { vm[method](script, ...args, options); },
41    {
42      code: 'ERR_SCRIPT_EXECUTION_INTERRUPTED',
43      message: 'Script execution was interrupted by `SIGINT`'
44    });
45  assert.strictEqual(firstHandlerCalled, 0);
46  assert.strictEqual(onceHandlerCalled, 0);
47
48  // Keep the process alive for a while so that the second SIGINT can be caught.
49  const timeout = setTimeout(() => {}, 1000);
50
51  let afterHandlerCalled = 0;
52
53  process.on('SIGINT', common.mustCall(() => {
54    // Handler attached _after_ execution.
55    if (afterHandlerCalled++ === 0) {
56      // The first time it just bounces back to check that the `once()`
57      // handler is not called the second time.
58      assert.strictEqual(firstHandlerCalled, 1);
59      assert.strictEqual(onceHandlerCalled, 1);
60      process.send(method);
61      return;
62    }
63
64    assert.strictEqual(onceHandlerCalled, 1);
65    assert.strictEqual(firstHandlerCalled, 2);
66    timeout.unref();
67  }, 2));
68
69  process.send(method);
70
71  return;
72}
73
74for (const method of methods) {
75  const child = spawn(process.execPath, [__filename, 'child', method], {
76    stdio: [null, 'inherit', 'inherit', 'ipc']
77  });
78
79  child.on('message', common.mustCall(() => {
80    // First kill() breaks the while(true) loop, second one invokes the real
81    // signal handlers.
82    process.kill(child.pid, 'SIGINT');
83  }, 3));
84
85  child.on('close', common.mustCall((code, signal) => {
86    assert.strictEqual(signal, null);
87    assert.strictEqual(code, 0);
88  }));
89}
90