Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
In a child process, each of the stdio streams may be set to
one of the following:
1. A new file descriptor in the child, dup2'ed to the parent and
exposed to JS as a Stream object.
2. A copy of a file descriptor from the parent, with no other
added magical stuff.
3. A black hole - no pipe created.
The trouble with using raw file descriptor integers for this is
that they are not portable to Windows.
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:
1. `null` or `undefined` - Use the default value. For 0,1,2,
this is the same as 'pipe'. For any higher value, 'ignore'
2. 'ignore' - Open the fd in the child, and /dev/null it
3. 'pipe' - Create a new dup2 pipe, and expose a stream object to JS.
4. 'ipc' - The same as 'pipe', but set up to send/receive IPC messages and
pass server/socket/FD handles for use with cluster.
Note: 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 a Node.js program, then
the presence of an IPC channel will enable process.send() and
5. positive integer - call tty_wrap.guessHandleType. Create the appropriate
pipe_wrap type of thing for this. Note that this will generally not
be a portable way to share a socket with the child process as a
stdio fd.
6. Any HandleWrap object - If the object is a HandleWrap object,
then the underlying TCP, Pipe, or File handle is shared with the
child process.
7. Any {handle:<instanceof HandleWrap>} object - If the object has a
`handle` member which is a HandleWrap object of some sort, then
treat this as #5.
8. Any {fd:<positive integer>} object - If the object has an ingeter `fd` member,
then treat this as #4.
9. Any negative integer: The same as 'pipe' (Backwards compatibility with
10. Anything else: throw.
As a shorthand, the `stdio` argument may also be one of the following
strings, rather than an array:
* `ignore` --> ['ignore', 'ignore', 'ignore']
* `pipe` --> ['pipe', 'pipe', 'pipe'] == [-1,-1,-1]
* `inherit` --> [process.stdin, process.stdout, process.stderr] == [0,1,2]
* `spawn`, `exec`, `execFile` --> ['pipe', 'pipe', 'pipe']
* `fork` --> ['ipc', 'pipe', 'pipe'] or ['ipc', 'ignore', 'ignore'] if
{ silent: true }
Since cluster just uses child_process.fork, it'll use the same defaults.
This will require a bit of refactoring in other parts of node besides
* TCP and TTY sockets have a "handle" member added and exposed explicitly.
* createPipe() should be blessed as a public API so that users can create
arbitrary duplex streams for stdio.
## createPipe([options])
* `options` {Object}
* `ipc` {Boolean} Default=false
* `readable` {Boolean} Default=true
* `writable` {Boolean} Default=true
* return: Pipe stream object
By default, all created pipes are duplex. The readable/writable aspect is
only set at the JavaScript layer to help prevent doing the wrong sort of
stream.pipe(). At the low-level, there is no special half-duplex behavior.
IPC is only enabled if explicitly requested, usually by setting 'ipc' as one
of the stdio FD options.
The return object is a Stream object. It has a "remote" member which
is an opaque object representing the other end of the pipe pair, and
is actually used by spawn.
var p = createPipe()
var c = spawn(cmd, args, { stdio: [ p ] })
p === c.stdin
p.on('data', function (chunk) {
console.error('c.stdin emitted data', chunk)
## Exposure on the ChildProcess object.
The stdin/stdout/stderr members will be set to a Stream object if set to
`pipe`, or null otherwise.
If an `ipc` channel was requested, then the ChildProcess object will have
a `send(msg)` method, and will perhaps `emit('message', obj)` if the child
writes JSON to that channel.
Other stdio fds will be exposed on the `stdio` member. ChildProcess.stdio
is an Array corresponding to the file descriptors opened in the child.
child.stdio[0] === child.stdin, child.stdio[2] === child.stderr, etc.
// Examples
// 1. spawn a child, taking over the parent's terminal.
spawn(cmd, args, { stdio: 'inherit' })
// 2. spawn a child, sharing only stderr
spawn(cmd, args, { stdio: ['pipe', 'pipe', process.stderr] })
// 3. since integer FDs will be inspected and set up appropriately,
// customFds-style will continue to work without modification
spawn(cmd, args, { stdio: [-1, -1, 2] })
// 4. Open an extra fd=4, to interact with programs present a
// startd-style interface.
spawn(cmd, args, { stdio: ['pipe', 'ignore', 'ignore', null, 'pipe'] })
// 5. Provide a socket as the stdin and stdio to a child,
// to interact with programs that present a cgi-style interface
net.createServer(function (conn) {
spawn(cmd, args, { stdio: [ conn, conn, process.stderr ] })
// 6. Same as #5, but log stderr to a file:'error.log', function (er, fd) {
if (er) throw er
net.createServer(function (conn) {
spawn(cmd, args, { stdio: [ conn, conn, fd ] })
// 7. like child_process.fork()
spawn(cmd, args, { stdio: [ 'ipc', 1, 2 ] })
// 7a. like child_process.fork(..., {silent: true})
spawn(cmd, args, { stdio: [ 'ipc', 'ignore', 'ignore' ] })
// 8. interact with some silly unix utility that uses a bunch of weird
// stdio stuff.
// * stdin is a pipe
// * stdout is a JS stream object
// * stderr is mapped to the parent's stdout
// * fd=3 is a JS stream object
// * fd=4 is ignored
// * fd=5 is the parent's stdin (eg, for the user to type in a pass phrase)
// * fd=6 writes to an error log
// * fd=7 can receive file descriptors and handles.
var rw = createPipe()
var ipc = createPipe({ipc: true})"log.txt", function (er, fd) {
if (er) throw er
spawn(cmd, args, { stdio: [ rw, 'pipe', process.stdout, 'pipe', null, 0, fd, ipc ] })

This comment has been minimized.

Copy link
Owner Author

isaacs commented Apr 3, 2012


This comment has been minimized.

Copy link

lsm commented Jan 22, 2016

@isaacs Do you have an example implementation for createPipe?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.