You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
71 lines
1.5 KiB
71 lines
1.5 KiB
'use strict';
|
|
|
|
function hasProcessExited(child) {
|
|
return !!(child.exitCode !== null || child.signalCode);
|
|
}
|
|
|
|
function onExitOnce(child) {
|
|
return new Promise(resolve => {
|
|
child.once('exit', () => resolve());
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Sends a kill signal to a child resolving when the child has exited,
|
|
* resorting to SIGKILL if the given timeout is reached
|
|
*
|
|
* @param {ChildProcess} child
|
|
* @param {'SIGTERM' | 'SIGKILL'} [signal] initial signal to use
|
|
* @param {number} [timeoutMs] time to wait until sending SIGKILL
|
|
*
|
|
* @returns {Promise<void>} the killed child
|
|
*/
|
|
function killAsync(child, signal, timeoutMs) {
|
|
if (hasProcessExited(child)) {
|
|
return Promise.resolve(child);
|
|
}
|
|
|
|
// catch any new on exit
|
|
let onExit = onExitOnce(child);
|
|
|
|
child.kill(signal || 'SIGKILL');
|
|
|
|
if (timeoutMs === 0 || isFinite(timeoutMs)) {
|
|
const timeout = setTimeout(() => {
|
|
if (!hasProcessExited(child)) {
|
|
child.kill('SIGKILL');
|
|
}
|
|
}, timeoutMs);
|
|
|
|
onExit = onExit.then(() => {
|
|
clearTimeout(timeout);
|
|
});
|
|
}
|
|
return onExit;
|
|
}
|
|
|
|
/*
|
|
asyncSend
|
|
Same as process.send but waits until the send is complete
|
|
the async version is used below because otherwise
|
|
the termination handler may exit before the parent
|
|
process has recived the messages it requires
|
|
*/
|
|
|
|
const asyncSend = (proc, msg) => {
|
|
return new Promise((resolve, reject) => {
|
|
proc.send(msg, err => {
|
|
if (err) {
|
|
reject(err);
|
|
} else {
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
};
|
|
|
|
module.exports = {
|
|
killAsync,
|
|
asyncSend
|
|
};
|