Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

Add disconnect method to forked child processes

This disconnect method allows the child to exit gracefully.
This also adds a disconnect event and connect property.
  • Loading branch information...
AndreasMadsen authored and piscisaureus committed Jan 30, 2012
1 parent 52bd0f9 commit 836344c90ed139f2e18bbcfb18d0ff2e2e42da81
Showing with 48 additions and 9 deletions.
  1. +13 −1 doc/api/child_processes.markdown
  2. +35 −8 lib/child_process.js
@@ -24,6 +24,13 @@ of the signal, otherwise `null`.

See `waitpid(2)`.

### Event: 'disconnect'

This event is emitted after using the `.disconnect()` method in the parent or
in the child. After disconnecting it is no longer possible to send messages.
An alternative way to check if you can send messages is to see if the
`child.connected` property is `true`.

### child.stdin

A `Writable Stream` that represents the child process's `stdin`.
@@ -264,7 +271,12 @@ processes:
}
});
To close the IPC connection between parent and child use the
`child.disconnect()` method. This allows the child to exit gracefully since
there is no IPC channel keeping it alive. When calling this method the
`disconnect` event will be emitted in both parent and child, and the
`connected` flag will be set to `false`. Please note that you can also call
`process.disconnect()` in the child process.
### child.kill([signal])
@@ -85,6 +85,7 @@ function setupChannel(target, channel) {
}
}

channel.buffering = false;
channel.onread = function(pool, offset, length, recvHandle) {
if (recvHandle && setSimultaneousAccepts) {
// Update simultaneous accepts on Windows
@@ -117,10 +118,11 @@ function setupChannel(target, channel) {
start = i + 1;
}
jsonBuffer = jsonBuffer.slice(start);
this.buffering = jsonBuffer.length !== 0;

} else {
channel.close();
target._channel = null;
this.buffering = false;
target.disconnect();
}
};

@@ -129,7 +131,7 @@ function setupChannel(target, channel) {
throw new TypeError('message cannot be undefined');
}

if (!target._channel) throw new Error("channel closed");
if (!this.connected) throw new Error("channel closed");

// For overflow protection don't write if channel queue is too deep.
if (channel.writeQueueSize > 1024 * 1024) {
@@ -154,6 +156,34 @@ function setupChannel(target, channel) {
return true;
};

target.connected = true;
target.disconnect = function() {
if (!this.connected) return;

// do not allow messages to be written
this.connected = false;
this._channel = null;

var fired = false;
function finish() {
if (fired) return;
fired = true;

channel.close();
target.emit('disconnect');
}

// If a message is being read, then wait for it to complete.
if (channel.buffering) {
this.once('message', finish);
this.once('internalMessage', finish);

return;
}

finish();
};

channel.readStart();
}

@@ -201,11 +231,8 @@ exports.fork = function(modulePath /*, args, options*/) {

if (!options.thread) setupChannel(child, options.stdinStream);

child.on('exit', function() {
if (child._channel) {
child._channel.close();
}
});
// Disconnect when the child process exits.
child.once('exit', child.disconnect.bind(child));

This comment has been minimized.

Copy link
@igorzi

igorzi Jan 31, 2012

This breaks when child is an isolate (there's no disconnect method).

This comment has been minimized.

Copy link
@AndreasMadsen

AndreasMadsen Jan 31, 2012

Author Member

Reported in #2647


return child;
};

0 comments on commit 836344c

Please sign in to comment.
You can’t perform that action at this time.