Skip to content

Commit

Permalink
child_process: expose UV_PROCESS_DETACHED as options.detached
Browse files Browse the repository at this point in the history
  • Loading branch information
AvianFlu authored and isaacs committed Jun 9, 2012
1 parent 5046f85 commit 4b021a3
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 5 deletions.
35 changes: 30 additions & 5 deletions doc/api/child_process.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ there is no IPC channel keeping it alive. When calling this method the
* `customFds` {Array} **Deprecated** File descriptors for the child to use
for stdio. (See below)
* `env` {Object} Environment key-value pairs
* `setsid` {Boolean}
* `detached` {Boolean} The child will be a process group leader. (See below)
* return: {ChildProcess object}

Launches a new process with the given `command`, with command line arguments in `args`.
Expand Down Expand Up @@ -342,7 +342,7 @@ index corresponds to a fd in the child. The value is one of the following:

1. `'pipe'` - Create a pipe between the child process and the parent process.
The parent end of the pipe is exposed to the parent as a property on the
child_process object as `ChildProcess.stdio[fd]`. Pipes created for
`child_process` object as `ChildProcess.stdio[fd]`. Pipes created for
fds 0 - 2 are also available as ChildProcess.stdin, ChildProcess.stdout
and ChildProcess.stderr, respectively.
2. `'ipc'` - Create an IPC channel for passing messages/file descriptors
Expand Down Expand Up @@ -387,6 +387,34 @@ Example:
// startd-style interface.
spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });

If the `detached` option is set, the child process will be made the leader of a
new process group. This makes it possible for the child to continue running
after the parent exits.

By default, the parent will wait for the detached child to exit. To prevent
the parent from waiting for a given `child`, use the `child.unref()` method,
and the parent's event loop will not include the child in its reference count.

Example of detaching a long-running process and redirecting its output to a
file:

var fs = require('fs'),
spawn = require('child_process').spawn,
out = fs.openSync('./out.log', 'a'),
err = fs.openSync('./out.log', 'a');

var child = spawn('prg', [], {
detached: 'true',
stdio: [ 'ignore', out, err ]
});

child.unref();

When using the `detached` option to start a long-running process, the process
will not stay running in the background unless it is provided with a `stdio`
configuration that is not connected to the parent. If the parent's `stdio` is
inherited, the child will remain attached to the controlling terminal.

There is a deprecated option called `customFds` which allows one to specify
specific file descriptors for the stdio of the child process. This API was
not portable to all platforms and therefore removed.
Expand All @@ -409,7 +437,6 @@ See also: `child_process.exec()` and `child_process.fork()`
* `customFds` {Array} **Deprecated** File descriptors for the child to use
for stdio. (See above)
* `env` {Object} Environment key-value pairs
* `setsid` {Boolean}
* `encoding` {String} (Default: 'utf8')
* `timeout` {Number} (Default: 0)
* `maxBuffer` {Number} (Default: 200*1024)
Expand Down Expand Up @@ -467,7 +494,6 @@ the child process is killed.
* `customFds` {Array} **Deprecated** File descriptors for the child to use
for stdio. (See above)
* `env` {Object} Environment key-value pairs
* `setsid` {Boolean}
* `encoding` {String} (Default: 'utf8')
* `timeout` {Number} (Default: 0)
* `maxBuffer` {Number} (Default: 200*1024)
Expand All @@ -490,7 +516,6 @@ leaner than `child_process.exec`. It has the same options.
* `options` {Object}
* `cwd` {String} Current working directory of the child process
* `env` {Object} Environment key-value pairs
* `setsid` {Boolean}
* `encoding` {String} (Default: 'utf8')
* `timeout` {Number} (Default: 0)
* Return: ChildProcess object
Expand Down
5 changes: 5 additions & 0 deletions lib/child_process.js
Original file line number Diff line number Diff line change
Expand Up @@ -602,12 +602,17 @@ var spawn = exports.spawn = function(file, args, options) {
args: args,
cwd: options ? options.cwd : null,
windowsVerbatimArguments: !!(options && options.windowsVerbatimArguments),
detached: !!(options && options.detached),
envPairs: envPairs,
stdio: options ? options.stdio : null,
uid: options ? options.uid : null,
gid: options ? options.gid : null
});

if (options && options.detached) {
child.unref();
}

return child;
};

Expand Down
5 changes: 5 additions & 0 deletions src/process_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,11 @@ class ProcessWrap : public HandleWrap {
options.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS;
}

//options.detached
if (js_options->Get(String::NewSymbol("detached"))->IsTrue()) {
options.flags |= UV_PROCESS_DETACHED;
}

int r = uv_spawn(uv_default_loop(), &wrap->process_, options);

if (r) {
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/child-process-persistent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
setInterval(function () {}, 500);
38 changes: 38 additions & 0 deletions test/simple/test-child-process-detached.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

var common = require('../common');
var assert = require('assert');
var path = require('path');

var spawn = require('child_process').spawn;
var childPath = path.join(__dirname, '..', 'fixtures', 'child-process-persistent.js');

var child = spawn(process.execPath, [ childPath ], {
detached: true,
stdio: 'ignore'
});

process.on('exit', function () {
process.kill(child.pid);
assert.throws(process.kill(child.pid), Error);
});

0 comments on commit 4b021a3

Please sign in to comment.