Skip to content

Commit b06d58b

Browse files
committed
[api] Expose Monitor.fork for using child_process.fork()
1 parent 2c6800a commit b06d58b

File tree

2 files changed

+56
-19
lines changed

2 files changed

+56
-19
lines changed

Diff for: lib/forever/monitor.js

+51-15
Original file line numberDiff line numberDiff line change
@@ -158,17 +158,17 @@ Monitor.prototype.start = function (restart) {
158158
self.emit(restart ? 'restart' : 'start', self, self.data);
159159
});
160160

161-
function reemit() {
162-
self.emit.apply(self, arguments);
161+
function onMessage(msg) {
162+
self.emit('message', msg);
163163
}
164164

165165
// Re-emit messages from the child process
166-
this.child.on('message', reemit);
166+
this.child.on('message', onMessage);
167167

168168
child.on('exit', function (code) {
169169
var spinning = Date.now() - self.ctime < self.minUptime;
170170
self.warn('Forever detected script exited with code: ' + code);
171-
child.removeListener('message', reemit);
171+
child.removeListener('message', onMessage);
172172

173173
function letChildDie() {
174174
self.running = false;
@@ -210,9 +210,6 @@ Monitor.prototype.start = function (restart) {
210210
// trying to execute a script with an env: e.g. node myfile.js
211211
//
212212
Monitor.prototype.trySpawn = function () {
213-
var execPath = process.execPath,
214-
forked;
215-
216213
if (this.command === 'node' || (this.checkFile && !this.childExists)) {
217214
try {
218215
var stats = fs.statSync(this.args[0]);
@@ -226,14 +223,9 @@ Monitor.prototype.trySpawn = function () {
226223
this.spawnWith.cwd = this.cwd || this.spawnWith.cwd;
227224
this.spawnWith.env = this._getEnv();
228225

229-
if (this.command === 'node' || this.fork) {
230-
process.execPath = this.command;
231-
forked = fork(this.options[0], this.options.slice(1), this.spawnWith);
232-
process.execPath = execPath;
233-
return forked;
234-
}
235-
236-
return spawn(this.command, this.options, this.spawnWith);
226+
return this.fork
227+
? this._forkSpawn()
228+
: spawn(this.command, this.options, this.spawnWith);
237229
};
238230

239231
//
@@ -402,3 +394,47 @@ Monitor.prototype._getEnv = function () {
402394

403395
return merged;
404396
};
397+
398+
//
399+
// ### @private function _forkSpawn()
400+
//
401+
// This is an unfortunate hack which works around two inconsistencies
402+
// in the `child_process` APIs in node.js core as of `v0.6.6`. Pull-requests
403+
// are open to resolve both issues.
404+
//
405+
// https://github.com/joyent/node/pull/2455
406+
// https://github.com/joyent/node/pull/2454
407+
//
408+
// Until then, setup `options.customFds` to always return null.
409+
//
410+
//
411+
Monitor.prototype._forkSpawn = function () {
412+
var execPath = process.execPath,
413+
hackSpawn = {},
414+
self = this,
415+
forked;
416+
417+
if (this.spawnWith && typeof this.spawnWith === 'object') {
418+
Object.keys(this.spawnWith).forEach(function (key) {
419+
hackSpawn[key] = self.spawnWith[key];
420+
});
421+
}
422+
423+
delete hackSpawn.customFds;
424+
Object.defineProperty(hackSpawn, 'customFds', {
425+
get: function () {
426+
return null;
427+
},
428+
set: function () {
429+
//
430+
// Do nothing, ignore the attempt to overwrite here:
431+
// https://github.com/joyent/node/blob/master/lib/child_process.js#L172
432+
//
433+
}
434+
});
435+
436+
process.execPath = this.command;
437+
forked = fork(this.options[0], this.options.slice(1), hackSpawn);
438+
process.execPath = execPath;
439+
return forked;
440+
};

Diff for: test/fork-test.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,19 @@ var assert = require('assert'),
1111
vows = require('vows'),
1212
forever = require('../lib/forever');
1313

14-
vows.describe('forever/spin-restart').addBatch({
14+
vows.describe('forever/fork').addBatch({
1515
"When using forever": {
1616
"and spawning a script that uses `process.send()`": {
1717
topic: function () {
1818
var script = path.join(__dirname, '..', 'examples', 'process-send.js'),
19-
child = new (forever.Monitor)(script, { silent: true, minUptime: 2000, max: 1 });
19+
child = new (forever.Monitor)(script, { silent: false, minUptime: 2000, max: 1, fork: true });
2020

2121
child.on('message', this.callback.bind(null, null));
2222
child.start();
2323
},
24-
"should reemit the message correctly": function (err, child, spinning) {
25-
console.dir(arguments);
24+
"should reemit the message correctly": function (err, msg) {
25+
assert.isObject(msg);
26+
assert.deepEqual(msg, { from: 'child' });
2627
}
2728
}
2829
}

0 commit comments

Comments
 (0)