Skip to content

Commit

Permalink
[api] Expose Monitor.fork for using child_process.fork()
Browse files Browse the repository at this point in the history
  • Loading branch information
indexzero committed Jan 5, 2012
1 parent 2c6800a commit b06d58b
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 19 deletions.
66 changes: 51 additions & 15 deletions lib/forever/monitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,17 +158,17 @@ Monitor.prototype.start = function (restart) {
self.emit(restart ? 'restart' : 'start', self, self.data);
});

function reemit() {
self.emit.apply(self, arguments);
function onMessage(msg) {
self.emit('message', msg);
}

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

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

function letChildDie() {
self.running = false;
Expand Down Expand Up @@ -210,9 +210,6 @@ Monitor.prototype.start = function (restart) {
// trying to execute a script with an env: e.g. node myfile.js
//
Monitor.prototype.trySpawn = function () {
var execPath = process.execPath,
forked;

if (this.command === 'node' || (this.checkFile && !this.childExists)) {
try {
var stats = fs.statSync(this.args[0]);
Expand All @@ -226,14 +223,9 @@ Monitor.prototype.trySpawn = function () {
this.spawnWith.cwd = this.cwd || this.spawnWith.cwd;
this.spawnWith.env = this._getEnv();

if (this.command === 'node' || this.fork) {
process.execPath = this.command;
forked = fork(this.options[0], this.options.slice(1), this.spawnWith);
process.execPath = execPath;
return forked;
}

return spawn(this.command, this.options, this.spawnWith);
return this.fork
? this._forkSpawn()
: spawn(this.command, this.options, this.spawnWith);
};

//
Expand Down Expand Up @@ -402,3 +394,47 @@ Monitor.prototype._getEnv = function () {

return merged;
};

//
// ### @private function _forkSpawn()
//
// This is an unfortunate hack which works around two inconsistencies
// in the `child_process` APIs in node.js core as of `v0.6.6`. Pull-requests
// are open to resolve both issues.
//
// https://github.com/joyent/node/pull/2455
// https://github.com/joyent/node/pull/2454
//
// Until then, setup `options.customFds` to always return null.
//
//
Monitor.prototype._forkSpawn = function () {
var execPath = process.execPath,
hackSpawn = {},
self = this,
forked;

if (this.spawnWith && typeof this.spawnWith === 'object') {
Object.keys(this.spawnWith).forEach(function (key) {
hackSpawn[key] = self.spawnWith[key];
});
}

delete hackSpawn.customFds;
Object.defineProperty(hackSpawn, 'customFds', {
get: function () {
return null;
},
set: function () {
//
// Do nothing, ignore the attempt to overwrite here:
// https://github.com/joyent/node/blob/master/lib/child_process.js#L172
//
}
});

process.execPath = this.command;
forked = fork(this.options[0], this.options.slice(1), hackSpawn);
process.execPath = execPath;
return forked;
};
9 changes: 5 additions & 4 deletions test/fork-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,19 @@ var assert = require('assert'),
vows = require('vows'),
forever = require('../lib/forever');

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

child.on('message', this.callback.bind(null, null));
child.start();
},
"should reemit the message correctly": function (err, child, spinning) {
console.dir(arguments);
"should reemit the message correctly": function (err, msg) {
assert.isObject(msg);
assert.deepEqual(msg, { from: 'child' });
}
}
}
Expand Down

0 comments on commit b06d58b

Please sign in to comment.