Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Commit

Permalink
src, lib: update after internal api change
Browse files Browse the repository at this point in the history
Libuv now returns errors directly.  Make everything in src/ and lib/
follow suit.

The changes to lib/ are not strictly necessary but they remove the need
for the abominations that are process._errno and node::SetErrno().
  • Loading branch information
bnoordhuis committed Jul 20, 2013
1 parent 0161ec8 commit ca9eb71
Show file tree
Hide file tree
Showing 25 changed files with 725 additions and 781 deletions.
75 changes: 38 additions & 37 deletions lib/child_process.js
Expand Up @@ -23,10 +23,13 @@ var StringDecoder = require('string_decoder').StringDecoder;
var EventEmitter = require('events').EventEmitter;
var net = require('net');
var dgram = require('dgram');
var Process = process.binding('process_wrap').Process;
var assert = require('assert');
var util = require('util');
var constants; // if (!constants) constants = process.binding('constants');

var Process = process.binding('process_wrap').Process;
var uv = process.binding('uv');

var constants; // Lazy-loaded process.binding('constants')

var errnoException = util._errnoException;
var handleWraps = {};
Expand Down Expand Up @@ -326,7 +329,8 @@ function setupChannel(target, channel) {
var decoder = new StringDecoder('utf8');
var jsonBuffer = '';
channel.buffering = false;
channel.onread = function(pool, recvHandle) {
channel.onread = function(nread, pool, recvHandle) {
// TODO(bnoordhuis) Check that nread > 0.
if (pool) {
jsonBuffer += decoder.write(pool);

Expand Down Expand Up @@ -449,22 +453,18 @@ function setupChannel(target, channel) {
return;
}

var req = { oncomplete: nop };
var string = JSON.stringify(message) + '\n';
var writeReq = channel.writeUtf8String(string, handle);
var err = channel.writeUtf8String(req, string, handle);

if (!writeReq) {
var er = errnoException(process._errno,
'write',
'cannot write to IPC channel.');
this.emit('error', er);
if (err) {
this.emit('error', errnoException(err, 'write'));
} else if (handle && !this._handleQueue) {
this._handleQueue = [];
}

if (obj && obj.postSend) {
writeReq.oncomplete = obj.postSend.bind(null, handle);
} else {
writeReq.oncomplete = nop;
req.oncomplete = obj.postSend.bind(null, handle);
}

/* If the master is > 2 read() calls behind, please stop sending. */
Expand Down Expand Up @@ -617,7 +617,7 @@ exports.execFile = function(file /* args, options, callback */) {
var exited = false;
var timeoutId;

var err;
var ex;

function exithandler(code, signal) {
if (exited) return;
Expand All @@ -630,21 +630,21 @@ exports.execFile = function(file /* args, options, callback */) {

if (!callback) return;

if (err) {
callback(err, stdout, stderr);
if (ex) {
callback(ex, stdout, stderr);
} else if (code === 0 && signal === null) {
callback(null, stdout, stderr);
} else {
var e = new Error('Command failed: ' + stderr);
e.killed = child.killed || killed;
e.code = code;
e.signal = signal;
callback(e, stdout, stderr);
ex = new Error('Command failed: ' + stderr);
ex.killed = child.killed || killed;
ex.code = code < 0 ? uv.errname(code) : code;
ex.signal = signal;
callback(ex, stdout, stderr);
}
}

function errorhandler(e) {
err = e;
ex = e;
child.stdout.destroy();
child.stderr.destroy();
exithandler();
Expand All @@ -658,7 +658,7 @@ exports.execFile = function(file /* args, options, callback */) {
try {
child.kill(options.killSignal);
} catch (e) {
err = e;
ex = e;
exithandler();
}
}
Expand All @@ -676,15 +676,15 @@ exports.execFile = function(file /* args, options, callback */) {
child.stdout.addListener('data', function(chunk) {
stdout += chunk;
if (stdout.length > options.maxBuffer) {
err = new Error('stdout maxBuffer exceeded.');
ex = new Error('stdout maxBuffer exceeded.');
kill();
}
});

child.stderr.addListener('data', function(chunk) {
stderr += chunk;
if (stderr.length > options.maxBuffer) {
err = new Error('stderr maxBuffer exceeded.');
ex = new Error('stderr maxBuffer exceeded.');
kill();
}
});
Expand Down Expand Up @@ -767,9 +767,9 @@ function ChildProcess() {
//
// new in 0.9.x:
//
// - spawn failures are reported with exitCode == -1
// - spawn failures are reported with exitCode < 0
//
var err = (exitCode == -1) ? errnoException(process._errno, 'spawn') : null;
var err = (exitCode < 0) ? errnoException(exitCode, 'spawn') : null;

if (signalCode) {
self.signalCode = signalCode;
Expand All @@ -784,7 +784,7 @@ function ChildProcess() {
self._handle.close();
self._handle = null;

if (exitCode == -1) {
if (exitCode < 0) {
self.emit('error', err);
} else {
self.emit('exit', self.exitCode, self.signalCode);
Expand Down Expand Up @@ -913,9 +913,9 @@ ChildProcess.prototype.spawn = function(options) {
options.envPairs.push('NODE_CHANNEL_FD=' + ipcFd);
}

var r = this._handle.spawn(options);
var err = this._handle.spawn(options);

if (r) {
if (err) {
// Close all opened fds on error
stdio.forEach(function(stdio) {
if (stdio.type === 'pipe') {
Expand All @@ -925,7 +925,7 @@ ChildProcess.prototype.spawn = function(options) {

this._handle.close();
this._handle = null;
throw errnoException(process._errno, 'spawn');
throw errnoException(err, 'spawn');
}

this.pid = this._handle.pid;
Expand Down Expand Up @@ -966,7 +966,7 @@ ChildProcess.prototype.spawn = function(options) {
// Add .send() method and start listening for IPC data
if (ipc !== undefined) setupChannel(this, ipc);

return r;
return err;
};


Expand All @@ -990,19 +990,20 @@ ChildProcess.prototype.kill = function(sig) {
}

if (this._handle) {
var r = this._handle.kill(signal);
if (r == 0) {
var err = this._handle.kill(signal);
if (err === 0) {
/* Success. */
this.killed = true;
return true;
} else if (process._errno == 'ESRCH') {
}
if (err === uv.UV_ESRCH) {
/* Already dead. */
} else if (process._errno == 'EINVAL' || process._errno == 'ENOSYS') {
} else if (err === uv.UV_EINVAL || err === uv.UV_ENOSYS) {
/* The underlying platform doesn't support this signal. */
throw errnoException(process._errno, 'kill');
throw errnoException(err, 'kill');
} else {
/* Other error, almost certainly EPERM. */
this.emit('error', errnoException(process._errno, 'kill'));
this.emit('error', errnoException(err, 'kill'));
}
}

Expand Down
41 changes: 26 additions & 15 deletions lib/cluster.js
Expand Up @@ -58,13 +58,20 @@ function SharedHandle(key, address, port, addressType, backlog, fd) {
this.key = key;
this.errno = '';
this.workers = [];
this.handle = null;
this.errno = 0;

// FIXME(bnoordhuis) Polymorphic return type for lack of a better solution.
var rval;
if (addressType === 'udp4' || addressType === 'udp6')
this.handle = dgram._createSocketHandle(address, port, addressType, fd);
rval = dgram._createSocketHandle(address, port, addressType, fd);
else
this.handle = net._createServerHandle(address, port, addressType, fd);
rval = net._createServerHandle(address, port, addressType, fd);

this.errno = this.handle ? '' : process._errno;
if (typeof rval === 'number')
this.errno = rval;
else
this.handle = rval;
}

SharedHandle.prototype.add = function(worker, send) {
Expand Down Expand Up @@ -116,10 +123,15 @@ RoundRobinHandle.prototype.add = function(worker, send) {

var self = this;
function done() {
if (self.handle.getsockname)
send(null, { sockname: self.handle.getsockname() }, null);
else
if (self.handle.getsockname) {
var out = {};
var err = self.handle.getsockname(out);
// TODO(bnoordhuis) Check err.
send(null, { sockname: out }, null);
}
else {
send(null, null, null); // UNIX socket.
}
self.handoff(worker); // In case there are connections pending.
}

Expand All @@ -143,7 +155,7 @@ RoundRobinHandle.prototype.remove = function(worker) {
return true;
};

RoundRobinHandle.prototype.distribute = function(handle) {
RoundRobinHandle.prototype.distribute = function(err, handle) {
this.handles.push(handle);
var worker = this.free.shift();
if (worker) this.handoff(worker);
Expand All @@ -164,7 +176,7 @@ RoundRobinHandle.prototype.handoff = function(worker) {
if (reply.accepted)
handle.close();
else
self.distribute(handle); // Worker is shutting down. Send to another.
self.distribute(0, handle); // Worker is shutting down. Send to another.
self.handoff(worker);
});
};
Expand Down Expand Up @@ -476,8 +488,9 @@ function workerInit() {

function onerror(message, cb) {
function listen(backlog) {
process._errno = message.errno;
return -1;
// Translate 'EADDRINUSE' error back to numeric value. This function
// is called as sock._handle.listen().
return process.binding('uv')['UV_' + message.errno];
}
function close() {
}
Expand All @@ -503,10 +516,8 @@ function workerInit() {
delete handles[key];
key = undefined;
}
function getsockname() {
var rv = {};
if (key) return util._extend(rv, message.sockname);
return rv;
function getsockname(out) {
if (key) util._extend(out, message.sockname);
}
// Faux handle. Mimics a TCPWrap with just enough fidelity to get away
// with it. Fools net.Server into thinking that it's backed by a real
Expand All @@ -530,7 +541,7 @@ function workerInit() {
var server = handles[key];
var accepted = (typeof server !== 'undefined');
send({ ack: message.seq, accepted: accepted });
if (accepted) server.onconnection(handle);
if (accepted) server.onconnection(0, handle);
}

Worker.prototype.disconnect = function() {
Expand Down

0 comments on commit ca9eb71

Please sign in to comment.