From 75c6d9dd95bbdb926d84cb3a9f518eff88651709 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Fri, 22 Jul 2016 12:05:27 -0400 Subject: [PATCH] cluster: support stdio option for workers This commit allows setupMaster() to configure the stdio channels for worker processes. Refs: https://github.com/nodejs/node-v0.x-archive/issues/5727 Refs: https://github.com/nodejs/node/pull/7811 PR-URL: https://github.com/nodejs/node/pull/7838 Reviewed-By: Santiago Gimeno Reviewed-By: James M Snell --- doc/api/cluster.md | 5 +++ lib/cluster.js | 1 + test/parallel/test-cluster-fork-stdio.js | 40 ++++++++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 test/parallel/test-cluster-fork-stdio.js diff --git a/doc/api/cluster.md b/doc/api/cluster.md index 6f0b424e05e083..616be9b59afd14 100644 --- a/doc/api/cluster.md +++ b/doc/api/cluster.md @@ -626,6 +626,9 @@ values are `"rr"` and `"none"`. (Default=`process.argv.slice(2)`) * `silent` {Boolean} whether or not to send output to parent's stdio. (Default=`false`) + * `stdio` {Array} Configures the stdio of forked processes. Because the + cluster module relies on IPC to function, this configuration must contain an + `'ipc'` entry. When this option is provided, it overrides `silent`. * `uid` {Number} Sets the user identity of the process. (See setuid(2).) * `gid` {Number} Sets the group identity of the process. (See setgid(2).) @@ -642,6 +645,8 @@ This object is not supposed to be changed or set manually, by you. (Default=`process.argv.slice(2)`) * `silent` {Boolean} whether or not to send output to parent's stdio. (Default=`false`) + * `stdio` {Array} Configures the stdio of forked processes. When this option + is provided, it overrides `silent`. `setupMaster` is used to change the default 'fork' behavior. Once called, the settings will be present in `cluster.settings`. diff --git a/lib/cluster.js b/lib/cluster.js index 38e6885f6757e9..05397ca69fba7f 100644 --- a/lib/cluster.js +++ b/lib/cluster.js @@ -322,6 +322,7 @@ function masterInit() { env: workerEnv, silent: cluster.settings.silent, execArgv: execArgv, + stdio: cluster.settings.stdio, gid: cluster.settings.gid, uid: cluster.settings.uid }); diff --git a/test/parallel/test-cluster-fork-stdio.js b/test/parallel/test-cluster-fork-stdio.js new file mode 100644 index 00000000000000..1d00e0768e5746 --- /dev/null +++ b/test/parallel/test-cluster-fork-stdio.js @@ -0,0 +1,40 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const cluster = require('cluster'); +const net = require('net'); + +if (cluster.isMaster) { + const buf = Buffer.from('foobar'); + + cluster.setupMaster({ + stdio: ['pipe', 'pipe', 'pipe', 'ipc', 'pipe'] + }); + + const worker = cluster.fork(); + const channel = worker.process.stdio[4]; + let response = ''; + + worker.on('exit', common.mustCall((code, signal) => { + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + })); + + channel.setEncoding('utf8'); + channel.on('data', (data) => { + response += data; + + if (response === buf.toString()) { + worker.disconnect(); + } + }); + channel.write(buf); +} else { + const pipe = new net.Socket({ fd: 4 }); + + pipe.unref(); + pipe.on('data', (data) => { + assert.ok(data instanceof Buffer); + pipe.write(data); + }); +}