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