From 07b199738887ecce3d14d54cbf1f97f159759a19 Mon Sep 17 00:00:00 2001 From: Andreas Madsen Date: Mon, 19 Dec 2011 20:48:03 +0100 Subject: [PATCH] Add env argument to cluster.fork Fixes 2378 --- doc/api/cluster.markdown | 6 ++- lib/cluster.js | 32 ++++++++++---- test/simple/test-cluster-fork-env.js | 66 ++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 test/simple/test-cluster-fork-env.js diff --git a/doc/api/cluster.markdown b/doc/api/cluster.markdown index 7f1b19c69f..b63ad26887 100644 --- a/doc/api/cluster.markdown +++ b/doc/api/cluster.markdown @@ -72,9 +72,11 @@ in the master process via message passing: -### cluster.fork() +### cluster.fork([env]) Spawn a new worker process. This can only be called from the master process. +The function takes an optional `env` object. The propertyies in this object +will be added to the process environment in the worker. ### cluster.isMaster ### cluster.isWorker @@ -92,6 +94,6 @@ This can be used to restart the worker by calling `fork()` again. console.log('worker ' + worker.pid + ' died. restart...'); cluster.fork(); }); - + Different techniques can be used to restart the worker depending on the application. diff --git a/lib/cluster.js b/lib/cluster.js index 6c7d2dfa83..91c3f1e45a 100644 --- a/lib/cluster.js +++ b/lib/cluster.js @@ -24,8 +24,21 @@ var fork = require('child_process').fork; var net = require('net'); var EventEmitter = require('events').EventEmitter; -var cluster = module.exports = new EventEmitter(); +function isObject(o) { + return (typeof o === 'object' && o !== null); +} +function extendObject(origin, add) { + console.log('object: ', add); + for (var name in add) { + if (Object.hasOwnProperty.call(add, name)) { + origin[name] = add[name]; + } + } + return origin; +} + +var cluster = module.exports = new EventEmitter(); var debug; if (process.env.NODE_DEBUG && /cluster/.test(process.env.NODE_DEBUG)) { @@ -139,7 +152,7 @@ function eachWorker(cb) { } -cluster.fork = function() { +cluster.fork = function(env) { // This can only be called from the master. assert(cluster.isMaster); @@ -147,15 +160,18 @@ cluster.fork = function() { startMaster(); var id = ++ids; - var envCopy = {}; - - for (var x in process.env) { - envCopy[x] = process.env[x]; - } + //Create env object + var envCopy = extendObject({}, process.env); envCopy['NODE_WORKER_ID'] = id; + if (isObject(env)) { + envCopy = extendObject(envCopy, env); + } - var worker = fork(workerFilename, workerArgs, { env: envCopy }); + //fork worker + var worker = fork(workerFilename, workerArgs, { + 'env': envCopy + }); workers[id] = worker; diff --git a/test/simple/test-cluster-fork-env.js b/test/simple/test-cluster-fork-env.js new file mode 100644 index 0000000000..f62f804fe2 --- /dev/null +++ b/test/simple/test-cluster-fork-env.js @@ -0,0 +1,66 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + +var common = require('../common'); +var assert = require('assert'); +var cluster = require('cluster'); + +if (cluster.isWorker) { + process.send({ + testcase: true, + prop: process.env['cluster_test_prop'], + overwrite: process.env['cluster_test_overwrite'] + }); + +} else if (cluster.isMaster) { + + var checks = { + using: false, + overwrite: false + }; + + //To check that the cluster extend on the process.env we will overwrite a + //property + process.env['cluster_test_overwrite'] = 'old'; + + //Fork worker + var worker = cluster.fork({ + 'cluster_test_prop': 'custom', + 'cluster_test_overwrite': 'new' + }); + + //Checks worker env + worker.on('message', function(data) { + if (data.testcase) { + checks.using = (data.prop === 'custom'); + checks.overwrite = (data.overwrite === 'new'); + process.exit(0); + } + }); + + process.once('exit', function() { + assert.ok(checks.using, 'The worker did not receive the correct env.'); + assert.ok(checks.overwrite, 'The custom environment did not overwrite ' + + 'the existing environment.'); + }); + +}