Browse Source

child_process: add keepOpen option to send()

This option allows an instance of net.Socket to be kept open in
the sending process.

Fixes: https://github.com/nodejs/node/issues/4271
PR-URL: https://github.com/nodejs/node/pull/5283
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
process-exit-stdio-flushing
cjihrig 9 years ago
parent
commit
e854f60585
  1. 7
      doc/api/child_process.markdown
  2. 14
      lib/internal/child_process.js
  3. 52
      test/parallel/test-child-process-send-keep-open.js

7
doc/api/child_process.markdown

@ -803,7 +803,12 @@ receive the object as the second argument passed to the callback function
registered on the `process.on('message')` event. registered on the `process.on('message')` event.
The `options` argument, if present, is an object used to parameterize the The `options` argument, if present, is an object used to parameterize the
sending of certain types of handles. sending of certain types of handles. `options` supports the following
properties:
* `keepOpen` - A Boolean value that can be used when passing instances of
`net.Socket`. When `true`, the socket is kept open in the sending process.
Defaults to `false`.
The optional `callback` is a function that is invoked after the message is 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 sent but before the child may have received it. The function is called with a

14
lib/internal/child_process.js

@ -78,21 +78,25 @@ const handleConversion = {
if (firstTime) socket.server._setupSlave(socketList); if (firstTime) socket.server._setupSlave(socketList);
// Act like socket is detached // Act like socket is detached
socket.server._connections--; if (!options.keepOpen)
socket.server._connections--;
} }
var handle = socket._handle;
// remove handle from socket object, it will be closed when the socket // remove handle from socket object, it will be closed when the socket
// will be sent // will be sent
var handle = socket._handle; if (!options.keepOpen) {
handle.onread = function() {}; handle.onread = function() {};
socket._handle = null; socket._handle = null;
}
return handle; return handle;
}, },
postSend: function(handle, options) { postSend: function(handle, options) {
// Close the Socket handle after sending it // Close the Socket handle after sending it
if (handle) if (handle && !options.keepOpen)
handle.close(); handle.close();
}, },

52
test/parallel/test-child-process-send-keep-open.js

@ -0,0 +1,52 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const cp = require('child_process');
const net = require('net');
if (process.argv[2] !== 'child') {
// The parent process forks a child process, starts a TCP server, and connects
// to the server. The accepted connection is passed to the child process,
// where the socket is written. Then, the child signals the parent process to
// write to the same socket.
let result = '';
process.on('exit', () => {
assert.strictEqual(result, 'childparent');
});
const child = cp.fork(__filename, ['child']);
// Verify that the child exits successfully
child.on('exit', common.mustCall((exitCode, signalCode) => {
assert.strictEqual(exitCode, 0);
assert.strictEqual(signalCode, null);
}));
const server = net.createServer((socket) => {
child.on('message', common.mustCall((msg) => {
assert.strictEqual(msg, 'child_done');
socket.end('parent', () => {
server.close();
child.disconnect();
});
}));
child.send('socket', socket, {keepOpen: true}, common.mustCall((err) => {
assert.ifError(err);
}));
});
server.listen(common.PORT, () => {
const socket = net.connect(common.PORT, common.localhostIPv4);
socket.setEncoding('utf8');
socket.on('data', (data) => result += data);
});
} else {
// The child process receives the socket from the parent, writes data to
// the socket, then signals the parent process to write
process.on('message', common.mustCall((msg, socket) => {
assert.strictEqual(msg, 'socket');
socket.write('child', () => process.send('child_done'));
}));
}
Loading…
Cancel
Save