diff --git a/lib/proc.js b/lib/proc.js index 846887c..20a2782 100644 --- a/lib/proc.js +++ b/lib/proc.js @@ -3,6 +3,7 @@ // This file is licensed under the MIT License. // License text available at https://opensource.org/licenses/MIT +var process = require('process'); var prog = require('child_process'); var cons = require('./console').Console; @@ -28,7 +29,10 @@ function run(key, proc, emitter) { file = '/bin/sh'; args = ['-c', proc.command]; } - var child = prog.spawn(file, args, { env: proc.env }); + var child = prog.spawn(file, args, { + env: proc.env, + detached: true, + }); var killallReceived = false; child.stdout.on('data', function(data) { @@ -59,7 +63,11 @@ function run(key, proc, emitter) { killallReceived = true; try { - child.kill(signal); + if (platform === 'win32') { + child.kill(signal); + } else { + process.kill(-child.pid, signal); + } } catch (err) { if (err.code === 'EPERM') { diff --git a/nf.js b/nf.js index 6ad22a4..c3ae8d3 100755 --- a/nf.js +++ b/nf.js @@ -46,8 +46,12 @@ var calculatePadding = _requirements.calculatePadding; var startProxies = require('./lib/proxy').startProxies; var startForward = require('./lib/forward').startForward; +var interrupted = false; + // Kill All Child Processes on SIGINT -process.once('SIGINT', function() { +process.on('SIGINT', function() { + if (interrupted) return; + interrupted = true; display.Warn('Interrupted by User'); emitter.emit('killall', 'SIGINT'); }); diff --git a/test/process-groups.test.sh b/test/process-groups.test.sh new file mode 100755 index 0000000..f25a778 --- /dev/null +++ b/test/process-groups.test.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +NF="node ../nf.js" + +rm -rf sandbox +mkdir -p sandbox + +cat << EOF > sandbox/Procfile +a: sleep 1 +b: /bin/sh -c "sleep 10000 && exit 1" +EOF + +# We'll exit with a code that cannot be used as a signal. This exposes a +# potential bug in termination handling. +$NF --procfile sandbox/Procfile start >sandbox/groups.txt 2>&1 && exit 0 +exit 1