1'use strict'; 2const common = require('../common'); 3const assert = require('assert'); 4const cp = require('child_process'); 5 6if (process.argv[2] === 'child') { 7 setTimeout(() => { 8 // The following console statements are part of the test. 9 console.log('child stdout'); 10 console.error('child stderr'); 11 }, common.platformTimeout(1000)); 12 return; 13} 14 15const cmd = `"${process.execPath}" "${__filename}" child`; 16 17// Test the case where a timeout is set, and it expires. 18cp.exec(cmd, { timeout: 1 }, common.mustCall((err, stdout, stderr) => { 19 let sigterm = 'SIGTERM'; 20 assert.strictEqual(err.killed, true); 21 // TODO OpenBSD returns a null signal and 143 for code 22 if (common.isOpenBSD) { 23 assert.strictEqual(err.code, 143); 24 sigterm = null; 25 } else { 26 assert.strictEqual(err.code, null); 27 } 28 // At least starting with Darwin Kernel Version 16.4.0, sending a SIGTERM to a 29 // process that is still starting up kills it with SIGKILL instead of SIGTERM. 30 // See: https://github.com/libuv/libuv/issues/1226 31 if (common.isOSX) 32 assert.ok(err.signal === 'SIGTERM' || err.signal === 'SIGKILL'); 33 else 34 assert.strictEqual(err.signal, sigterm); 35 assert.strictEqual(err.cmd, cmd); 36 assert.strictEqual(stdout.trim(), ''); 37 assert.strictEqual(stderr.trim(), ''); 38})); 39 40// Test with a different kill signal. 41cp.exec(cmd, { 42 timeout: 1, 43 killSignal: 'SIGKILL' 44}, common.mustCall((err, stdout, stderr) => { 45 assert.strictEqual(err.killed, true); 46 assert.strictEqual(err.code, null); 47 assert.strictEqual(err.signal, 'SIGKILL'); 48 assert.strictEqual(err.cmd, cmd); 49 assert.strictEqual(stdout.trim(), ''); 50 assert.strictEqual(stderr.trim(), ''); 51})); 52 53// Test the case where a timeout is set, but not expired. 54cp.exec(cmd, { timeout: 2 ** 30 }, common.mustCall((err, stdout, stderr) => { 55 assert.ifError(err); 56 assert.strictEqual(stdout.trim(), 'child stdout'); 57 assert.strictEqual(stderr.trim(), 'child stderr'); 58})); 59 60// Workaround for Windows Server 2008R2 61// When CMD is used to launch a process and CMD is killed too quickly, the 62// process can stay behind running in suspended state, never completing. 63if (common.isWindows) { 64 process.once('beforeExit', () => { 65 const basename = __filename.replace(/.*[/\\]/g, ''); 66 cp.execFileSync(`${process.env.SystemRoot}\\System32\\wbem\\WMIC.exe`, [ 67 'process', 68 'where', 69 `commandline like '%${basename}%child'`, 70 'delete', 71 '/nointeractive' 72 ]); 73 }); 74} 75