doc: improve child_process.markdown copy
authorJames M Snell <jasnell@gmail.com>
Mon, 21 Dec 2015 21:48:43 +0000 (13:48 -0800)
committerMyles Borins <mborins@us.ibm.com>
Wed, 2 Mar 2016 22:01:11 +0000 (14:01 -0800)
General improvements to child_process.markdown

PR-URL: https://github.com/nodejs/node/pull/4383
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
doc/api/child_process.markdown

index 1ab5322..029b63f 100644 (file)
 
     Stability: 2 - Stable
 
-Node.js provides a tri-directional `popen(3)` facility through the
-`child_process` module.
-
-It is possible to stream data through a child's `stdin`, `stdout`, and
-`stderr` in a fully non-blocking way.  (Note that some programs use
-line-buffered I/O internally.  That doesn't affect Node.js but it means
-data you send to the child process may not be immediately consumed.)
-
-To create a child process, use `require('child_process').spawn()` or
-`require('child_process').fork()`.  The semantics of each are slightly
-different as explained [below][].
-
-For scripting purposes you may find the [synchronous counterparts][] more
-convenient.
-
-## Class: ChildProcess
-
-`ChildProcess` is an [`EventEmitter`][].
-
-Child processes always have three streams associated with them. `child.stdin`,
-`child.stdout`, and `child.stderr`.  These may be shared with the stdio
-streams of the parent process, or they may be separate stream objects
-which can be piped to and from.
-
-The `ChildProcess` class is not intended to be used directly.  Use the
-[`spawn()`][], [`exec()`][], [`execFile()`][], or [`fork()`][] methods to create
-an instance of `ChildProcess`.
-
-### Event: 'close'
-
-* `code` {Number} the exit code, if it exited normally.
-* `signal` {String} the signal passed to kill the child process, if it
-  was killed by the parent.
-
-This event is emitted when the stdio streams of a child process have all
-terminated.  This is distinct from `'exit'`, since multiple processes
-might share the same stdio streams.
-
-### Event: 'disconnect'
-
-This event is emitted after calling the `.disconnect()` method in the parent
-or in the child. After disconnecting it is no longer possible to send messages,
-and the `.connected` property is false.
-
-### Event:  'error'
-
-* `err` {Error Object} the error.
-
-Emitted when:
-
-1. The process could not be spawned, or
-2. The process could not be killed, or
-3. Sending a message to the child process failed.
-
-Note that the `'exit'` event may or may not fire after an error has occurred.
-If you are listening on both events to fire a function, remember to guard
-against calling your function twice.
-
-See also [`ChildProcess#kill()`][] and [`ChildProcess#send()`][].
-
-### Event:  'exit'
-
-* `code` {Number} the exit code, if it exited normally.
-* `signal` {String} the signal passed to kill the child process, if it
-  was killed by the parent.
-
-This event is emitted after the child process ends. If the process terminated
-normally, `code` is the final exit code of the process, otherwise `null`. If
-the process terminated due to receipt of a signal, `signal` is the string name
-of the signal, otherwise `null`.
-
-Note that the child process stdio streams might still be open.
-
-Also, note that Node.js establishes signal handlers for `SIGINT` and
-`SIGTERM`. It will not terminate due to receipt of those signals. It will exit.
-
-See `waitpid(2)`.
-
-### Event: 'message'
-
-* `message` {Object} a parsed JSON object or primitive value.
-* `sendHandle` {Handle object} a [`net.Socket`][] or [`net.Server`][] object, or
-  undefined.
-
-Messages sent by `.send(message, [sendHandle])` are obtained using the
-`'message'` event.
-
-### child.connected
-
-* {Boolean} Set to false after `.disconnect` is called
-
-If `.connected` is false, it is no longer possible to send messages.
-
-### child.disconnect()
-
-Close the IPC channel between parent and child, allowing the child to exit
-gracefully once there are no other connections keeping it alive. After calling
-this method the `.connected` flag will be set to `false` in both the parent and
-child, and it is no longer possible to send messages.
-
-The `'disconnect'` event will be emitted when there are no messages in the
-process of being received, most likely immediately.
-
-Note that you can also call `process.disconnect()` in the child process when the
-child process has any open IPC channels with the parent (i.e [`fork()`][]).
-
-### child.kill([signal])
-
-* `signal` {String}
-
-Send a signal to the child process. If no argument is given, the process will
-be sent `'SIGTERM'`. See `signal(7)` for a list of available signals.
+The `child_process` module provides the ability to spawn child processes in
+a manner that is similar, but not identical, to [`popen(3)`][]. This capability
+is primarily provided by the `child_process.spawn()` function:
 
     const spawn = require('child_process').spawn;
-    const grep = spawn('grep', ['ssh']);
+    const ls = spawn('ls', ['-lh', '/usr']);
 
-    grep.on('close', (code, signal) => {
-      console.log(
-        `child process terminated due to receipt of signal ${signal}`);
+    ls.stdout.on('data', (data) => {
+      console.log(`stdout: ${data}`);
     });
 
-    // send SIGHUP to process
-    grep.kill('SIGHUP');
-
-May emit an `'error'` event when the signal cannot be delivered. Sending a
-signal to a child process that has already exited is not an error but may
-have unforeseen consequences. Specifically, if the process identifier (PID) has
-been reassigned to another process, the signal will be delivered to that
-process instead. What happens next is anyone's guess.
-
-Note that while the function is called `kill`, the signal delivered to the
-child process may not actually kill it.  `kill` really just sends a signal
-to a process.
-
-See `kill(2)`
-
-### child.pid
-
-* {Integer}
-
-The process identifier (PID) of the child process.
-
-Example:
-
-    const spawn = require('child_process').spawn;
-    const grep = spawn('grep', ['ssh']);
-
-    console.log(`Spawned child pid: ${grep.pid}`);
-    grep.stdin.end();
-
-### child.send(message[, sendHandle][, callback])
-
-* `message` {Object}
-* `sendHandle` {Handle object}
-* `callback` {Function}
-* Return: Boolean
-
-When using [`child_process.fork()`][] you can write to the child using
-`child.send(message[, sendHandle][, callback])` and messages are received by
-a `'message'` event on the child.
-
-For example:
-
-    const cp = require('child_process');
-    const n = cp.fork(`${__dirname}/sub.js`);
-
-    n.on('message', (m) => {
-      console.log('PARENT got message:', m);
+    ls.stderr.on('data', (data) => {
+      console.log(`stderr: ${data}`);
     });
 
-    n.send({ hello: 'world' });
-
-And then the child script, `'sub.js'` might look like this:
-
-    process.on('message', (m) => {
-      console.log('CHILD got message:', m);
+    ls.on('close', (code) => {
+      console.log(`child process exited with code ${code}`);
     });
 
-    process.send({ foo: 'bar' });
-
-In the child, the `process` object will have a `send()` method, and `process`
-will emit objects each time it receives a message on its channel.
+By default, pipes for `stdin`, `stdout` and `stderr` are established between
+the parent Node.js process and the spawned child. It is possible to stream data
+through these pipes in a non-blocking way. *Note, however, that some programs
+use line-buffered I/O internally. While that does not affect Node.js, it can
+mean that data sent to the child process may not be immediately consumed.*
+
+The `child_process.spawn()` method spawns the child process asynchronously,
+without blocking the Node.js event loop. The `child_process.spawnSync()`
+function provides equivalent functionality in a synchronous manner that blocks
+the event loop until the spawned process either exits of is terminated.
+
+For convenience, the `child_process` module provides a handful of synchronous
+and asynchronous alternatives to `child_process.spawn()` and
+`child_process.spawnSync()`, each of which are documented fully [below][].
+*Note that each of these alternatives are implemented on top of
+`child_process.spawn()` or `child_process.spawnSync()`.*
+
+  * `child_process.exec()`: spawns a shell and runs a command within that shell,
+    passing the `stdout` and `stderr` to a callback function when complete.
+  * `child_process.execFile()`: similar to `child_process.exec()` except that
+    it spawns the command directly without first spawning a shell.
+  * `child_process.fork()`: spawns a new Node.js process and invokes a
+    specified module with an IPC communication channel established that allows
+    sending messages between parent and child.
+  * `child_process.execSync()`: a synchronous version of
+    `child_process.exec()` that *will* block the Node.js event loop.
+  * `child_process.execFileSync()`: a synchronous version of
+    `child_process.execFile()` that *will* block the Node.js event loop.
+
+For certain use cases, such as automating shell scripts, the
+[synchronous counterparts][] may be more convenient. In many cases, however,
+the synchronous methods can have significant impact on performance due to
+stalling the event loop while spawned processes complete.
 
-There is a special case when sending a `{cmd: 'NODE_foo'}` message. All messages
-containing a `NODE_` prefix in its `cmd` property will not be emitted in
-the `'message'` event, since they are internal messages used by Node.js core.
-Messages containing the prefix are emitted in the `'internalMessage'` event.
-Avoid using this feature; it is subject to change without notice.
-
-The `sendHandle` option to `child.send()` is for sending a TCP server or
-socket object to another process. The child will receive the object as its
-second argument to the `'message'` event.
+## Asynchronous Process Creation
 
-The `callback` option is a function that is invoked after the message is
-sent but before the target may have received it.  It is called with a single
-argument: `null` on success, or an [`Error`][] object on failure.
+The `child_process.spawn()`, `child_process.fork()`, `child_process.exec()`,
+and `child_process.execFile()` methods all follow the idiomatic asynchronous
+programming pattern typical of other Node.js APIs.
 
-`child.send()` emits an `'error'` event if no callback was given and the message
-cannot be sent, for example because the child process has already exited.
+Each of the methods returns a [ChildProcess][] instance. These objects
+implement the Node.js [EventEmitter][] API, allowing the parent process to
+register listener functions that are called when certain events occur during
+the life cycle of the child process.
 
-Returns `true` under normal circumstances or `false` when the backlog of
-unsent messages exceeds a threshold that makes it unwise to send more.
-Use the callback mechanism to implement flow control.
+The `child_process.exec()` and `child_process.execFile()` methods additionally
+allow for an optional `callback` function to be specified that is invoked
+when the child process terminates.
 
-#### Example: sending server object
+### Spawning `.bat` and `.cmd` files on Windows
 
-Here is an example of sending a server:
+The importance of the distinction between `child_process.exec()` and
+`child_process.execFile()` can vary based on platform. On Unix-type operating
+systems (Unix, Linux, OSX) `child_process.execFile()` can be more efficient
+because it does not spawn a shell. On Windows, however, `.bat` and `.cmd`
+files are not executable on their own without a terminal and therefore cannot
+be launched using `child_process.execFile()` (or even `child_process.spawn()`).
+When running on Windows, `.bat` and `.cmd` files can only be invoked using
+either `child_process.exec()` or by spawning `cmd.exe` and passing the `.bat`
+or `.cmd` file as an argument (which is what `child_process.exec()` does).
 
-    const child = require('child_process').fork('child.js');
+    // On Windows Only ...
+    const spawn = require('child_process').spawn;
+    const bat = spawn('cmd.exe', ['/c', 'my.bat']);
 
-    // Open up the server object and send the handle.
-    const server = require('net').createServer();
-    server.on('connection', (socket) => {
-      socket.end('handled by parent');
-    });
-    server.listen(1337, () => {
-      child.send('server', server);
+    bat.stdout.on('data', (data) => {
+      console.log(data);
     });
 
-And the child would then receive the server object as:
-
-    process.on('message', (m, server) => {
-      if (m === 'server') {
-        server.on('connection', (socket) => {
-          socket.end('handled by child');
-        });
-      }
+    bat.stderr.on('data', (data) => {
+      console.log(data);
     });
 
-Note that the server is now shared between the parent and child, this means
-that some connections will be handled by the parent and some by the child.
-
-For `dgram` servers the workflow is exactly the same.  Here you listen on
-a `'message'` event instead of `'connection'` and use `server.bind` instead of
-`server.listen`.  (Currently only supported on UNIX platforms.)
-
-#### Example: sending socket object
-
-Here is an example of sending a socket. It will spawn two children and handle
-connections with the remote address `74.125.127.100` as VIP by sending the
-socket to a "special" child process. Other sockets will go to a "normal"
-process.
-
-    const normal = require('child_process').fork('child.js', ['normal']);
-    const special = require('child_process').fork('child.js', ['special']);
-
-    // Open up the server and send sockets to child
-    const server = require('net').createServer();
-    server.on('connection', (socket) => {
-
-      // if this is a VIP
-      if (socket.remoteAddress === '74.125.127.100') {
-        special.send('socket', socket);
-        return;
-      }
-      // just the usual...
-      normal.send('socket', socket);
+    bat.on('exit', (code) => {
+      console.log(`Child exited with code ${code}`);
     });
-    server.listen(1337);
-
-The `child.js` could look like this:
 
-    process.on('message', (m, socket) => {
-      if (m === 'socket') {
-        socket.end(`You were handled as a ${process.argv[2]} person`);
+    // OR...
+    const exec = require('child_process').exec;
+    exec('my.bat', (err, stdout, stderr) => {
+      if (err) {
+        console.error(err);
+        return;
       }
+      console.log(stdout);
     });
 
-Note that once a single socket has been sent to a child the parent can no
-longer keep track of when the socket is destroyed. To indicate this condition
-the `.connections` property becomes `null`.
-It is also recommended not to use `.maxConnections` in this condition.
-
-### child.stderr
-
-* {Stream object}
-
-A `Readable Stream` that represents the child process's `stderr`.
-
-If the child was not spawned with `stdio[2]` set to `'pipe'`, then this will
-not be set.
-
-`child.stderr` is shorthand for `child.stdio[2]`. Both properties will refer
-to the same object, or null.
-
-### child.stdin
-
-* {Stream object}
-
-A `Writable Stream` that represents the child process's `stdin`.
-If the child is waiting to read all its input, it will not continue until this
-stream has been closed via `end()`.
-
-If the child was not spawned with `stdio[0]` set to `'pipe'`, then this will
-not be set.
-
-`child.stdin` is shorthand for `child.stdio[0]`. Both properties will refer
-to the same object, or null.
-
-### child.stdio
-
-* {Array}
-
-A sparse array of pipes to the child process, corresponding with positions in
-the [`stdio`][] option to [`spawn()`][] that have been set to `'pipe'`.
-Note that streams 0-2 are also available as ChildProcess.stdin,
-ChildProcess.stdout, and ChildProcess.stderr, respectively.
-
-In the following example, only the child's fd `1` is setup as a pipe, so only
-the parent's `child.stdio[1]` is a stream, all other values in the array are
-`null`.
-
-    const assert = require('assert');
-    const fs = require('fs');
-    const child_process = require('child_process');
-
-    const child = child_process.spawn('ls', {
-        stdio: [
-          0, // use parents stdin for child
-          'pipe', // pipe child's stdout to parent
-          fs.openSync('err.out', 'w') // direct child's stderr to a file
-        ]
-    });
-
-    assert.equal(child.stdio[0], null);
-    assert.equal(child.stdio[0], child.stdin);
-
-    assert(child.stdout);
-    assert.equal(child.stdio[1], child.stdout);
-
-    assert.equal(child.stdio[2], null);
-    assert.equal(child.stdio[2], child.stderr);
-
-### child.stdout
-
-* {Stream object}
-
-A `Readable Stream` that represents the child process's `stdout`.
-
-If the child was not spawned with `stdio[1]` set to `'pipe'`, then this will
-not be set.
-
-`child.stdout` is shorthand for `child.stdio[1]`. Both properties will refer
-to the same object, or null.
-
-## Asynchronous Process Creation
-
-These methods follow the common async programming patterns (accepting a
-callback or returning an EventEmitter).
-
-### child_process.exec(command[, options], callback)
+### child_process.exec(command[, options][, callback])
 
 * `command` {String} The command to run, with space-separated arguments
 * `options` {Object}
@@ -375,7 +131,8 @@ callback or returning an EventEmitter).
   * `stderr` {Buffer}
 * Return: ChildProcess object
 
-Runs a command in a shell and buffers the output.
+Spawns a shell then executes the `command` within that shell, buffering any
+generated output.
 
     const exec = require('child_process').exec;
     const child = exec('cat *.js bad_file | wc -l',
@@ -387,29 +144,35 @@ Runs a command in a shell and buffers the output.
         }
     });
 
-The callback gets the arguments `(error, stdout, stderr)`. On success, `error`
-will be `null`.  On error, `error` will be an instance of [`Error`][] and `error.code`
-will be the exit code of the child process, and `error.signal` will be set to the
-signal that terminated the process.
+If a `callback` function is provided, it is called with the arguments
+`(error, stdout, stderr)`. On success, `error` will be `null`.  On error,
+`error` will be an instance of [`Error`][]. The `error.code` property will be
+the exit code of the child process while `error.signal` will be set to the
+signal that terminated the process. Any exit code other than `0` is considered
+to be an error.
 
-There is a second optional argument to specify several options. The
-default options are
+The `options` argument may be passed as the second argument to customize how
+the process is spawned. The default options are:
 
-    { encoding: 'utf8',
+    {
+      encoding: 'utf8',
       timeout: 0,
       maxBuffer: 200*1024,
       killSignal: 'SIGTERM',
       cwd: null,
-      env: null }
+      env: null
+    }
 
-If `timeout` is greater than 0, then it will kill the child process
-if it runs longer than `timeout` milliseconds. The child process is killed with
-`killSignal` (default: `'SIGTERM'`). `maxBuffer` specifies the largest
-amount of data (in bytes) allowed on stdout or stderr - if this value is
-exceeded then the child process is killed.
+If `timeout` is greater than `0`, the parent will send the the signal
+identified by the `killSignal` property (the default is `'SIGTERM'`) if the
+child runs longer than `timeout` milliseconds.
 
-*Note: Unlike the `exec()` POSIX system call, `child_process.exec()` does not replace
-the existing process and uses a shell to execute the command.*
+The `maxBuffer` option specifies the largest amount of data (in bytes) allowed
+on stdout or stderr - if this value is exceeded then the child process is
+terminated.
+
+*Note: Unlike the `exec()` POSIX system call, `child_process.exec()` does not
+replace the existing process and uses a shell to execute the command.*
 
 ### child_process.execFile(file[, args][, options][, callback])
 
@@ -431,10 +194,21 @@ the existing process and uses a shell to execute the command.*
   * `stderr` {Buffer}
 * Return: ChildProcess object
 
-This is similar to [`child_process.exec()`][] except it does not execute a
-subshell but rather the specified file directly. This makes it slightly
-leaner than [`child_process.exec()`][]. It has the same options.
+The `child_process.execFile()` method is similar to [`child_process.exec()`][]
+except that it does not first spawn a shell. Rather, the specified `command` is
+spawned directly as a new process making it slightly more efficient than
+[`child_process.exec()`][]. The same options are support by both
+`child_process.exec()` and `child_process.execFile()`.
 
+    const exec = require('child_process').execFile;
+    const child = execFile('cat *.js bad_file | wc -l',
+      (error, stdout, stderr) => {
+        console.log(`stdout: ${stdout}`);
+        console.log(`stderr: ${stderr}`);
+        if (error !== null) {
+          console.log(`exec error: ${error}`);
+        }
+    });
 
 ### child_process.fork(modulePath[, args][, options])
 
@@ -454,23 +228,31 @@ leaner than [`child_process.exec()`][]. It has the same options.
   * `gid` {Number} Sets the group identity of the process. (See setgid(2).)
 * Return: ChildProcess object
 
-This is a special case of the [`child_process.spawn()`][] functionality for
-spawning Node.js processes. In addition to having all the methods in a normal
-ChildProcess instance, the returned object has a communication channel built-in.
-See [`ChildProcess#send()`][] for details.
-
-These child Node.js processes are still whole new instances of V8. Assume at
-least 30ms startup and 10mb memory for each new Node.js. That is, you cannot
-create many thousands of them.
-
-The `execPath` property in the `options` object allows for a process to be
-created for the child rather than the current `node` executable. This should be
-done with care and by default will talk over the fd represented an
-environmental variable `NODE_CHANNEL_FD` on the child process. The input and
+The `child_process.fork()` method is a special case of
+[`child_process.spawn()`][] used specifically to spawn new Node.js processes.
+Like `child_process.spawn()`, a `ChildProcess` object is returned. The returned
+`ChildProcess` will have an additional communication channel built-in that
+allows messages to be passed back and forth between the parent and child. See
+[`ChildProcess#send()`][] for details.
+
+It is important to keep in mind that spawned Node.js child processes are
+independent of the parent with exception of the IPC communication channel
+that is established between the two. Each process has it's own memory, with
+their own V8 instances. Because of the additional resource allocations
+required, spawning a large number of child Node.js processes is not
+recommended.
+
+By default, `child_process.fork()` will spawn new Node.js instances using the
+`process.execPath` of the parent process. The `execPath` property in the
+`options` object allows for an alternative execution path to be used.
+
+Node.js processes launched with a custom `execPath` will communicate with the
+parent process using the file descriptor (fd) identified using the
+environment variable `NODE_CHANNEL_FD` on the child process. The input and
 output on this fd is expected to be line delimited JSON objects.
 
-*Note: Unlike the `fork()` POSIX system call, [`child_process.fork()`][] does not clone the
-current process.*
+*Note: Unlike the `fork()` POSIX system call, [`child_process.fork()`][] does
+not clone the current process.*
 
 ### child_process.spawn(command[, args][, options])
 
@@ -488,12 +270,14 @@ current process.*
   * `gid` {Number} Sets the group identity of the process. (See setgid(2).)
 * return: {ChildProcess object}
 
-Launches a new process with the given `command`, with  command line arguments in
-`args`. If omitted, `args` defaults to an empty Array.
+The `child_process.spawn()` method spawns a new process using the given
+`command`, with command line arguments in `args`. If omitted, `args` defaults
+to an empty array.
 
-The third argument is used to specify additional options, with these defaults:
+A third argument may be used to specify additional options, with these defaults:
 
-    { cwd: undefined,
+    {
+      cwd: undefined,
       env: process.env
     }
 
@@ -503,7 +287,8 @@ If not given, the default is to inherit the current working directory.
 Use `env` to specify environment variables that will be visible to the new
 process, the default is `process.env`.
 
-Example of running `ls -lh /usr`, capturing `stdout`, `stderr`, and the exit code:
+Example of running `ls -lh /usr`, capturing `stdout`, `stderr`, and the
+exit code:
 
     const spawn = require('child_process').spawn;
     const ls = spawn('ls', ['-lh', '/usr']);
@@ -568,18 +353,21 @@ Example of checking for failed exec:
 
 #### options.detached
 
-On Windows, this makes it possible for the child to continue running after the
-parent exits. The child will have a new console window (this cannot be
-disabled).
+On Windows, setting `options.detached` to `true` makes it possible for the
+child process to continue running after the parent exits. The child will have
+its own console window. *Once enabled for a child process, it cannot be
+disabled*.
 
-On non-Windows, if the `detached` option is set, the child process will be made
-the leader of a new process group and session. Note that child processes may
-continue running after the parent exits whether they are detached or not.  See
-`setsid(2)` for more information.
+On non-Windows platforms, if `options.detached` is set to `true`, the child
+process will be made the leader of a new process group and session. Note that
+child processes may continue running after the parent exits regardless of
+whether they are detached or not.  See `setsid(2)` for more information.
 
-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.
+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.
+Doing so will cause the parent's event loop to not include the child in its
+reference count, allowing the parent to exit independently of the child, unless
+there is an established IPC channel between the child and parent.
 
 Example of detaching a long-running process and redirecting its output to a
 file:
@@ -604,14 +392,23 @@ controlling terminal.
 
 #### options.stdio
 
-As a shorthand, the `stdio` argument may be one of the following strings:
+The `options.stdio` option is used to configure the pipes that are established
+between the parent and child process. By default, the child's stdin, stdout,
+and stderr are redirected to corresponding `child.stdin`, `child.stdout`, and
+`child.stderr` streams on the `ChildProcess` object. This is equivalent to
+setting the `options.stdio` equal to `['pipe', 'pipe', 'pipe']`.
+
+For convenience, `options.stdio` may be one of the following strings:
 
-* `'pipe'` - `['pipe', 'pipe', 'pipe']`, this is the default value
-* `'ignore'` - `['ignore', 'ignore', 'ignore']`
-* `'inherit'` - `[process.stdin, process.stdout, process.stderr]` or `[0,1,2]`
+* `'pipe'` - equivalent to `['pipe', 'pipe', 'pipe']` (the default)
+* `'ignore'` - equivalent to `['ignore', 'ignore', 'ignore']`
+* `'inherit'` - equivalent to `[process.stdin, process.stdout, process.stderr]`
+   or `[0,1,2]`
 
-Otherwise, the `'stdio'` option to [`child_process.spawn()`][] is an array where each
-index corresponds to a fd in the child.  The value is one of the following:
+Otherwise, the value of `option.stdio` is an array where each index corresponds
+to an fd in the child. The fds 0, 1, and 2 correspond to stdin, stdout,
+and stderr, respectively. Additional fds can be specified to create additional
+pipes between the parent and 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
@@ -621,13 +418,15 @@ index corresponds to a fd in the child.  The value is one of the following:
 2. `'ipc'` - Create an IPC channel for passing messages/file descriptors
    between parent and child. A ChildProcess may have at most *one* IPC stdio
    file descriptor. Setting this option enables the ChildProcess.send() method.
-   If the child writes JSON messages to this file descriptor, then this will
-   trigger ChildProcess.on('message').  If the child is an Node.js program, then
-   the presence of an IPC channel will enable process.send() and
-   process.on('message').
-3. `'ignore'` - Do not set this file descriptor in the child. Note that Node.js
-   will always open fd 0 - 2 for the processes it spawns. When any of these is
-   ignored Node.js will open `/dev/null` and attach it to the child's fd.
+   If the child writes JSON messages to this file descriptor, the
+   `ChildProcess.on('message')` event handler will be triggered in the parent.
+   If the child is a Node.js process, the presence of an IPC channel will enable
+   `process.send()`, `process.disconnect()`, `process.on('disconnect')`, and
+   `process.on('message')` within the child.
+3. `'ignore'` - Instructs Node.js to ignore the fd in the child. While Node.js
+   will always open fds 0 - 2 for the processes it spawns, setting the fd to
+   `'ignore'` will cause Node.js to open `/dev/null` and attach it to the
+   child's fd.
 4. `Stream` object - Share a readable or writable stream that refers to a tty,
    file, socket, or a pipe with the child process. The stream's underlying
    file descriptor is duplicated in the child process to the fd that
@@ -651,16 +450,25 @@ Example:
     // Spawn child sharing only stderr
     spawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] });
 
-    // Open an extra fd=4, to interact with programs present a
+    // Open an extra fd=4, to interact with programs presenting a
     // startd-style interface.
     spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });
 
+*It is worth noting that when an IPC channel is established between the
+parent and child processes, and the child is a Node.js process, the child
+is launched with the IPC channel unreferenced (using `unref()`) until the
+child registers an event handler for the `process.on('disconnected')` event.
+This allows the child to exit normally without the process being held open
+by the open IPC channel.*
+
 See also: [`child_process.exec()`][] and [`child_process.fork()`][]
 
 ## Synchronous Process Creation
 
-These methods are **synchronous**, meaning they **WILL** block the event loop,
-pausing execution of your code until the spawned process exits.
+The `child_process.spawnSync()`, `child_process.execSync()`, and
+`child_process.execFileSync()` methods are **synchronous** and **WILL** block
+the Node.js event loop, pausing execution of any additional code until the
+spawned process exits.
 
 Blocking calls like these are mostly useful for simplifying general purpose
 scripting tasks and for simplifying the loading/processing of application
@@ -687,11 +495,13 @@ configuration at startup.
   * `encoding` {String} The encoding used for all stdio inputs and outputs. (Default: 'buffer')
 * return: {Buffer|String} The stdout from the command
 
-`execFileSync` will not return until the child process has fully closed. When a
-timeout has been encountered and `killSignal` is sent, the method won't return
-until the process has completely exited. That is to say, if the process handles
-the `SIGTERM` signal and doesn't exit, your process will wait until the child
-process has exited.
+The `child_process.execFileSync()` method is generally identical to
+`child_process.execFile()` with the exception that the method will not return
+until the child process has fully closed. When a timeout has been encountered
+and `killSignal` is sent, the method won't return until the process has
+completely exited. *Note that if the child process intercepts and handles
+the `SIGTERM` signal and does not exit, the parent process will still wait
+until the child process has exited.*
 
 If the process times out, or has a non-zero exit code, this method ***will***
 throw.  The [`Error`][] object will contain the entire result from
@@ -721,11 +531,13 @@ throw.  The [`Error`][] object will contain the entire result from
   * `encoding` {String} The encoding used for all stdio inputs and outputs. (Default: 'buffer')
 * return: {Buffer|String} The stdout from the command
 
-`execSync` will not return until the child process has fully closed. When a
-timeout has been encountered and `killSignal` is sent, the method won't return
-until the process has completely exited. That is to say, if the process handles
-the `SIGTERM` signal and doesn't exit, your process will wait until the child
-process has exited.
+The `child_process.execSync()` method is generally identical to
+`child_process.exec()` with the exception that the method will not return until
+the child process has fully closed. When a timeout has been encountered and
+`killSignal` is sent, the method won't return until the process has completely
+exited. *Note that if  the child process intercepts and handles the `SIGTERM`
+signal and doesn't exit, the parent process will wait until the child
+process has exited.*
 
 If the process times out, or has a non-zero exit code, this method ***will***
 throw.  The [`Error`][] object will contain the entire result from
@@ -757,26 +569,370 @@ throw.  The [`Error`][] object will contain the entire result from
   * `signal` {String} The signal used to kill the child process
   * `error` {Error} The error object if the child process failed or timed out
 
-`spawnSync` will not return until the child process has fully closed. When a
-timeout has been encountered and `killSignal` is sent, the method won't return
-until the process has completely exited. That is to say, if the process handles
-the `SIGTERM` signal and doesn't exit, your process will wait until the child
+The `child_process.spawnSync()` method is generally identical to
+`child_process.spawn()` with the exception that the function will not return
+until the child process has fully closed. When a timeout has been encountered
+and `killSignal` is sent, the method won't return until the process has
+completely exited. Note that if the process intercepts and handles the
+`SIGTERM` signal and doesn't exit, the parent process will wait until the child
 process has exited.
 
+## Class: ChildProcess
+
+Instances of the `ChildProcess` class are [`EventEmitters`][] that represent
+spawned child processes.
+
+Instances of `ChildProcess` are not intended to be created directly. Rather,
+use the [`child_process.spawn()`][], [`child_process.exec()`][],
+[`child_process.execFile()`][], or [`child_process.fork()`][] methods to create
+instances of `ChildProcess`.
+
+### Event: 'close'
+
+* `code` {Number} the exit code if the child exited on its own.
+* `signal` {String} the signal by which the child process was terminated.
+
+The `'close'` event is emitted when the stdio streams of a child process have
+been closed. This is distinct from the `'exit'` event, since multiple
+processes might share the same stdio streams.
+
+### Event: 'disconnect'
+
+The `'disconnect'` event is emitted after calling the
+`ChildProcess.disconnect()` method in the parent or child process. After
+disconnecting it is no longer possible to send or receive messages, and the
+`ChildProcess.connected` property is false.
+
+### Event:  'error'
+
+* `err` {Error Object} the error.
+
+The `'error'` event is emitted whenever:
+
+1. The process could not be spawned, or
+2. The process could not be killed, or
+3. Sending a message to the child process failed.
+
+Note that the `'exit'` event may or may not fire after an error has occurred.
+If you are listening to both the `'exit'` and `'error'` events, it is important
+to guard against accidentally invoking handler functions multiple times.
+
+See also [`ChildProcess#kill()`][] and [`ChildProcess#send()`][].
+
+### Event:  'exit'
+
+* `code` {Number} the exit code if the child exited on its own.
+* `signal` {String} the signal by which the child process was terminated.
+
+The `'exit'` event is emitted after the child process ends. If the process
+exited, `code` is the final exit code of the process, otherwise `null`. If the
+process terminated due to receipt of a signal, `signal` is the string name of
+the signal, otherwise `null`. One of the two will always be non-null.
+
+Note that when the `'exit'` event is triggered, child process stdio streams
+might still be open.
+
+Also, note that Node.js establishes signal handlers for `SIGINT` and
+`SIGTERM` and Node.js processes will not terminate immediately due to receipt
+of those signals. Rather, Node.js will perform a sequence of cleanup actions
+and then will re-raise the handled signal.
+
+See `waitpid(2)`.
+
+### Event: 'message'
+
+* `message` {Object} a parsed JSON object or primitive value.
+* `sendHandle` {Handle object} a [`net.Socket`][] or [`net.Server`][] object, or
+  undefined.
+
+The `'message'` event is triggered when a child process uses `process.send()`
+to send messages.
+
+### child.connected
+
+* {Boolean} Set to false after `.disconnect` is called
+
+The `child.connected` property indicates whether it is still possible to send
+and receive messages from a child process. When `child.connected` is false, it
+is no longer possible to send or receive messages.
+
+### child.disconnect()
+
+Closes the IPC channel between parent and child, allowing the child to exit
+gracefully once there are no other connections keeping it alive. After calling
+this method the `child.connected` and `process.connected` properties in both
+the parent and child (respectively) will be set to `false`, and it will be no
+longer possible to pass messages between the processes.
+
+The `'disconnect'` event will be emitted when there are no messages in the
+process of being received. This will most often be triggered immediately after
+calling `child.disconnect()`.
+
+Note that when the child process is a Node.js instance (e.g. spawned using
+[`child_process.fork()`]), the `process.disconnect()` method can be invoked
+within the child process to close the IPC channel as well.
+
+### child.kill([signal])
+
+* `signal` {String}
+
+The `child.kill()` methods sends a signal to the child process. If no argument
+is given, the process will be sent the `'SIGTERM'` signal. See `signal(7)` for
+a list of available signals.
+
+    const spawn = require('child_process').spawn;
+    const grep = spawn('grep', ['ssh']);
+
+    grep.on('close', (code, signal) => {
+      console.log(
+        `child process terminated due to receipt of signal ${signal}`);
+    });
+
+    // Send SIGHUP to process
+    grep.kill('SIGHUP');
+
+The `ChildProcess` object may emit an `'error'` event if the signal cannot be
+delivered. Sending a signal to a child process that has already exited is not
+an error but may have unforeseen consequences. Specifically, if the process
+identifier (PID) has been reassigned to another process, the signal will be
+delivered to that process instead which can have unexpected results.
+
+Note that while the function is called `kill`, the signal delivered to the
+child process may not actually terminate the process.
+
+See `kill(2)`
+
+### child.pid
+
+* {Integer}
+
+Returns the process identifier (PID) of the child process.
+
+Example:
+
+    const spawn = require('child_process').spawn;
+    const grep = spawn('grep', ['ssh']);
+
+    console.log(`Spawned child pid: ${grep.pid}`);
+    grep.stdin.end();
+
+### child.send(message[, sendHandle][, callback])
+
+* `message` {Object}
+* `sendHandle` {Handle object}
+* `callback` {Function}
+* Return: Boolean
+
+When an IPC channel has been established between the parent and child (
+i.e. when using [`child_process.fork()`][]), the `child.send()` method can be
+used to send messages to the child process. When the child process is a Node.js
+instance, these messages can be received via the `process.on('message')` event.
+
+For example, in the parent script:
+
+    const cp = require('child_process');
+    const n = cp.fork(`${__dirname}/sub.js`);
+
+    n.on('message', (m) => {
+      console.log('PARENT got message:', m);
+    });
+
+    n.send({ hello: 'world' });
+
+And then the child script, `'sub.js'` might look like this:
+
+    process.on('message', (m) => {
+      console.log('CHILD got message:', m);
+    });
+
+    process.send({ foo: 'bar' });
+
+Child Node.js processes will have a `process.send()` method of their own that
+allows the child to send messages back to the parent.
+
+There is a special case when sending a `{cmd: 'NODE_foo'}` message. All messages
+containing a `NODE_` prefix in its `cmd` property are considered to be reserved
+for use within Node.js core and will not be emitted in the child's
+`process.on('message')` event. Rather, such messages are emitted using the
+`process.on('internalMessage')` event and are consumed internally by Node.js.
+Applications should avoid using such messages or listening for
+`'internalMessage'` events as it is subject to change without notice.
+
+The optional `sendHandle` argument that may be passed to `child.send()` is for
+passing a TCP server or socket object to the child process. The child will
+receive the object as the second argument passed to the callback function
+registered on the `process.on('message')` event.
+
+The optional `callback` is a function that is invoked after the message is
+sent but before the child may have received it.  The function is called with a
+single argument: `null` on success, or an [`Error`][] object on failure.
+
+If no `callback` function is provided and the message cannot be sent, an
+`'error'` event will be emitted by the `ChildProcess` object. This can happen,
+for instance, when the child process has already exited.
+
+`child.send()` will return `false` if the channel has closed or when the
+backlog of unsent messages exceeds a threshold that makes it unwise to send
+more. Otherwise, the method returns `true`. The `callback` function can be
+used to implement flow control.
+
+#### Example: sending a server object
+
+The `sendHandle` argument can be used, for instance, to pass the handle of
+a TSCP server object to the child process as illustrated in the example below:
+
+    const child = require('child_process').fork('child.js');
+
+    // Open up the server object and send the handle.
+    const server = require('net').createServer();
+    server.on('connection', (socket) => {
+      socket.end('handled by parent');
+    });
+    server.listen(1337, () => {
+      child.send('server', server);
+    });
+
+The child would then receive the server object as:
+
+    process.on('message', (m, server) => {
+      if (m === 'server') {
+        server.on('connection', (socket) => {
+          socket.end('handled by child');
+        });
+      }
+    });
+
+Once the server is now shared between the parent and child, some connections
+can be handled by the parent and some by the child.
+
+While the example above uses a server created using the `net` module, `dgram`
+module servers use exactly the same workflow with the exceptions of listening on
+a `'message'` event instead of `'connection'` and using `server.bind` instead of
+`server.listen`. This is, however, currently only supported on UNIX platforms.
+
+#### Example: sending a socket object
+
+Similarly, the `sendHandler` argument can be used to pass the handle of a
+socket to the child process. The example below spawns two children that each
+handle connections with "normal" or "special" priority:
+
+    const normal = require('child_process').fork('child.js', ['normal']);
+    const special = require('child_process').fork('child.js', ['special']);
+
+    // Open up the server and send sockets to child
+    const server = require('net').createServer();
+    server.on('connection', (socket) => {
+
+      // If this is special priority
+      if (socket.remoteAddress === '74.125.127.100') {
+        special.send('socket', socket);
+        return;
+      }
+      // This is normal priority
+      normal.send('socket', socket);
+    });
+    server.listen(1337);
+
+The `child.js` would receive the socket handle as the second argument passed
+to the event callback function:
+
+    process.on('message', (m, socket) => {
+      if (m === 'socket') {
+        socket.end(`Request handled with ${process.argv[2]} priority`);
+      }
+    });
+
+Once a socket has been passed to a child, the parent is no longer capable of
+tracking when the socket is destroyed. To indicate this, the `.connections`
+property becomes `null`. It is recommended not to use `.maxConnections` when
+this occurs.
+
+### child.stderr
+
+* {Stream object}
+
+A `Readable Stream` that represents the child process's `stderr`.
+
+If the child was spawned with `stdio[2]` set to anything other than `'pipe'`,
+then this will be `undefined`.
+
+`child.stderr` is an alias for `child.stdio[2]`. Both properties will refer to
+the same value.
+
+### child.stdin
+
+* {Stream object}
+
+A `Writable Stream` that represents the child process's `stdin`.
+
+*Note that if a child process waits to read all of its input, the child will not
+continue until this stream has been closed via `end()`.*
+
+If the child was spawned with `stdio[0]` set to anything other than `'pipe'`,
+then this will be `undefined`.
+
+`child.stdin` is an alias for `child.stdio[0]`. Both properties will refer to
+the same value.
+
+### child.stdio
+
+* {Array}
+
+A sparse array of pipes to the child process, corresponding with positions in
+the [`stdio`][] option passed to [`child_process.spawn()`][] that have been set
+to the value `'pipe'`. Note that `child.stdio[0]`, `child.stdio[1]`, and
+`child.stdio[2]` are also available as `child.stdin`, `child.stdout`, and
+`child.stderr`, respectively.
+
+In the following example, only the child's fd `1` (stdout) is configured as a
+pipe, so only the parent's `child.stdio[1]` is a stream, all other values in
+the array are `null`.
+
+    const assert = require('assert');
+    const fs = require('fs');
+    const child_process = require('child_process');
+
+    const child = child_process.spawn('ls', {
+        stdio: [
+          0, // Use parents stdin for child
+          'pipe', // Pipe child's stdout to parent
+          fs.openSync('err.out', 'w') // Direct child's stderr to a file
+        ]
+    });
+
+    assert.equal(child.stdio[0], null);
+    assert.equal(child.stdio[0], child.stdin);
+
+    assert(child.stdout);
+    assert.equal(child.stdio[1], child.stdout);
+
+    assert.equal(child.stdio[2], null);
+    assert.equal(child.stdio[2], child.stderr);
+
+### child.stdout
+
+* {Stream object}
+
+A `Readable Stream` that represents the child process's `stdout`.
+
+If the child was spawned with `stdio[1]` set to anything other than `'pipe'`,
+then this will be `undefined`.
+
+`child.stdout` is an alias for `child.stdio[1]`. Both properties will refer
+to the same value.
+
+[`popen(3)`]: http://linux.die.net/man/3/popen
 [`child_process.exec()`]: #child_process_child_process_exec_command_options_callback
+[`child_process.execFile()`]: #child_process_child_process_execfile_file_args_options_callback
 [`child_process.fork()`]: #child_process_child_process_fork_modulepath_args_options
 [`child_process.spawn()`]: #child_process_child_process_spawn_command_args_options
 [`child_process.spawnSync()`]: #child_process_child_process_spawnsync_command_args_options
 [`ChildProcess#kill()`]: #child_process_child_kill_signal
 [`ChildProcess#send()`]: #child_process_child_send_message_sendhandle_callback
 [`Error`]: errors.html#errors_class_error
-[`EventEmitter`]: events.html#events_class_events_eventemitter
-[`exec()`]: #child_process_child_process_exec_command_options_callback
-[`execFile()`]: #child_process_child_process_execfile_file_args_options_callback
-[`fork()`]: #child_process_child_process_fork_modulepath_args_options
+[`EventEmitters`]: events.html#events_class_events_eventemitter
 [`net.Server`]: net.html#net_class_net_server
 [`net.Socket`]: net.html#net_class_net_socket
-[`spawn()`]: #child_process_child_process_spawn_command_args_options
 [`stdio`]: #child_process_options_stdio
 [below]: #child_process_asynchronous_process_creation
 [synchronous counterparts]: #child_process_synchronous_process_creation