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.mustSucceed((stdout, stderr) => { 55 assert.strictEqual(stdout.trim(), 'child stdout'); 56 assert.strictEqual(stderr.trim(), 'child stderr'); 57})); 58 59// Workaround for Windows Server 2008R2 60// When CMD is used to launch a process and CMD is killed too quickly, the 61// process can stay behind running in suspended state, never completing. 62if (common.isWindows) { 63 process.once('beforeExit', () => { 64 const basename = __filename.replace(/.*[/\\]/g, ''); 65 cp.execFileSync(`${process.env.SystemRoot}\\System32\\wbem\\WMIC.exe`, [ 66 'process', 67 'where', 68 `commandline like '%${basename}%child'`, 69 'delete', 70 '/nointeractive', 71 ]); 72 }); 73} 74