From 0e6ba3ce6d3ad19f1348e547d15136b3c789732b Mon Sep 17 00:00:00 2001 From: Marcel Kottmann Date: Fri, 7 Jun 2019 16:40:32 +0200 Subject: [PATCH] fix: wait for all subprocesses to terminate (fixes issue #1476) --- lib/monitor/run.js | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/lib/monitor/run.js b/lib/monitor/run.js index 7084c6bf..bf48ab2d 100644 --- a/lib/monitor/run.js +++ b/lib/monitor/run.js @@ -16,6 +16,28 @@ var psTree = require('pstree.remy'); var path = require('path'); var signals = require('./signals'); +function waitForSubprocesses(subprocesses, callback) { + if (Array.isArray(subprocesses) && subprocesses.length > 0) { + // check if all old subprocesses have been terminated + exec('kill -0 ' + subprocesses.join(' '), (error) => { + const returnCode = error ? error.code : 0; + if (returnCode < 126) { // ignore command not found error + const stillRunning = subprocesses.length - returnCode; + if (stillRunning > 0) { + utils.log.status('still waiting for ' + stillRunning + + ' subprocess(es) to finish...'); + setTimeout(waitForSubprocesses.bind(this, subprocesses, callback), + 100); + return; + } + } + callback(); + }); + } else { + callback(); + } +} + function run(options) { var cmd = config.command.raw; @@ -341,17 +363,24 @@ function kill(child, signal, callback) { // configured signal (default: SIGUSR2) signal, which fixes #335 // note that psTree also works if `ps` is missing by looking in /proc const sig = signal.replace('SIG', ''); - psTree(child.pid, function (err, kids) { + psTree(child.pid, function (err, subprocesses) { if (psTree.hasPS) { - spawn('kill', ['-s', sig, child.pid].concat(kids)) - .on('close', callback); + spawn('kill', ['-s', sig].concat(subprocesses)) + .on('close', waitForSubprocesses.bind(this, subprocesses, + function () { + spawn('kill', ['-s', sig, child.pid]) + .on('close', callback); + })); } else { // make sure we kill from smallest to largest - const pids = kids.concat(child.pid).sort(); + const pids = subprocesses.slice().sort(); pids.forEach(pid => { exec('kill -' + signals[signal] + ' ' + pid, () => { }); }); - callback(); + waitForSubprocesses(subprocesses, function () { + exec('kill -' + signals[signal] + ' ' + child.pid, () => { }); + callback(); + }) } });