aboutsummaryrefslogtreecommitdiff
path: root/node_modules/foreground-child/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/foreground-child/index.js')
-rw-r--r--node_modules/foreground-child/index.js102
1 files changed, 102 insertions, 0 deletions
diff --git a/node_modules/foreground-child/index.js b/node_modules/foreground-child/index.js
new file mode 100644
index 000000000..32ae9ff57
--- /dev/null
+++ b/node_modules/foreground-child/index.js
@@ -0,0 +1,102 @@
+var signalExit = require('signal-exit')
+var spawn = require('child_process').spawn
+if (process.platform === 'win32') {
+ spawn = require('cross-spawn')
+}
+
+module.exports = function (program, args, cb) {
+ var arrayIndex = arguments.length
+
+ if (typeof args === 'function') {
+ cb = args
+ args = undefined
+ } else {
+ cb = Array.prototype.slice.call(arguments).filter(function (arg, i) {
+ if (typeof arg === 'function') {
+ arrayIndex = i
+ return true
+ }
+ })[0]
+ }
+
+ cb = cb || function (done) {
+ return done()
+ }
+
+ if (Array.isArray(program)) {
+ args = program.slice(1)
+ program = program[0]
+ } else if (!Array.isArray(args)) {
+ args = [].slice.call(arguments, 1, arrayIndex)
+ }
+
+ var spawnOpts = { stdio: [0, 1, 2] }
+
+ if (process.send) {
+ spawnOpts.stdio.push('ipc')
+ }
+
+ var child = spawn(program, args, spawnOpts)
+
+ var childExited = false
+ var unproxySignals = proxySignals(child)
+ process.on('exit', childHangup)
+ function childHangup () {
+ child.kill('SIGHUP')
+ }
+
+ child.on('close', function (code, signal) {
+ // Allow the callback to inspect the child’s exit code and/or modify it.
+ process.exitCode = signal ? 128 + signal : code
+
+ cb(function () {
+ unproxySignals()
+ process.removeListener('exit', childHangup)
+ childExited = true
+ if (signal) {
+ // If there is nothing else keeping the event loop alive,
+ // then there's a race between a graceful exit and getting
+ // the signal to this process. Put this timeout here to
+ // make sure we're still alive to get the signal, and thus
+ // exit with the intended signal code.
+ setTimeout(function () {}, 200)
+ process.kill(process.pid, signal)
+ } else {
+ // Equivalent to process.exit() on Node.js >= 0.11.8
+ process.exit(process.exitCode)
+ }
+ })
+ })
+
+ if (process.send) {
+ process.removeAllListeners('message')
+
+ child.on('message', function (message, sendHandle) {
+ process.send(message, sendHandle)
+ })
+
+ process.on('message', function (message, sendHandle) {
+ child.send(message, sendHandle)
+ })
+ }
+
+ return child
+}
+
+function proxySignals (child) {
+ var listeners = {}
+ signalExit.signals().forEach(function (sig) {
+ listeners[sig] = function () {
+ child.kill(sig)
+ }
+ process.on(sig, listeners[sig])
+ })
+
+ return unproxySignals
+
+ function unproxySignals () {
+ for (var sig in listeners) {
+ process.removeListener(sig, listeners[sig])
+ }
+ }
+}