From 9e7a2e251ac3ec94e489f69b19fd96d3a80c6094 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_ child processes to terminate (fixes issue #1476) --- lib/monitor/run.js | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/monitor/run.js b/lib/monitor/run.js index 7084c6bf..1dddece2 100644 --- a/lib/monitor/run.js +++ b/lib/monitor/run.js @@ -15,6 +15,25 @@ var restart = null; var psTree = require('pstree.remy'); var path = require('path'); var signals = require('./signals'); +var oldKids; + +function waitForOldKids(callback) { + if (oldKids) { + // check if all previous kids have been terminated + exec('kill -0 ' + oldKids.join(' '), (error) => { + const stillRunningKids = oldKids.length - (error ? error.code : 0); + if (stillRunningKids > 0) { + utils.log.status('still waiting for ' + stillRunningKids + + ' child process(es) to finish...'); + setTimeout(waitForOldKids.bind(this, callback), 100); + } else { + callback(); + } + }); + } else { + callback(); + } +} function run(options) { var cmd = config.command.raw; @@ -25,7 +44,14 @@ function run(options) { } /*jshint validthis:true*/ - restart = run.bind(this, options); + var runbinded = run.bind(this, options); + + if (utils.isWindows) { + restart = runbinded; + } else { + restart = waitForOldKids.bind(this, runbinded); + } + run.restart = restart; config.lastStarted = Date.now(); @@ -80,7 +106,7 @@ function run(options) { var inBinPath = false; try { inBinPath = statSync(`${binPath}/${executable}`).isFile(); - } catch (e) {} + } catch (e) { } // hasStdio allows us to correctly handle stdin piping // see: https://git.io/vNtX3 @@ -342,6 +368,7 @@ function kill(child, signal, callback) { // note that psTree also works if `ps` is missing by looking in /proc const sig = signal.replace('SIG', ''); psTree(child.pid, function (err, kids) { + oldKids = kids; if (psTree.hasPS) { spawn('kill', ['-s', sig, child.pid].concat(kids)) .on('close', callback);