Skip to content

Commit ca9eb71

Browse files
committed
src, lib: update after internal api change
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().
1 parent 0161ec8 commit ca9eb71

25 files changed

+725
-781
lines changed

lib/child_process.js

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,13 @@ var StringDecoder = require('string_decoder').StringDecoder;
2323
var EventEmitter = require('events').EventEmitter;
2424
var net = require('net');
2525
var dgram = require('dgram');
26-
var Process = process.binding('process_wrap').Process;
2726
var assert = require('assert');
2827
var util = require('util');
29-
var constants; // if (!constants) constants = process.binding('constants');
28+
29+
var Process = process.binding('process_wrap').Process;
30+
var uv = process.binding('uv');
31+
32+
var constants; // Lazy-loaded process.binding('constants')
3033

3134
var errnoException = util._errnoException;
3235
var handleWraps = {};
@@ -326,7 +329,8 @@ function setupChannel(target, channel) {
326329
var decoder = new StringDecoder('utf8');
327330
var jsonBuffer = '';
328331
channel.buffering = false;
329-
channel.onread = function(pool, recvHandle) {
332+
channel.onread = function(nread, pool, recvHandle) {
333+
// TODO(bnoordhuis) Check that nread > 0.
330334
if (pool) {
331335
jsonBuffer += decoder.write(pool);
332336

@@ -449,22 +453,18 @@ function setupChannel(target, channel) {
449453
return;
450454
}
451455

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

455-
if (!writeReq) {
456-
var er = errnoException(process._errno,
457-
'write',
458-
'cannot write to IPC channel.');
459-
this.emit('error', er);
460+
if (err) {
461+
this.emit('error', errnoException(err, 'write'));
460462
} else if (handle && !this._handleQueue) {
461463
this._handleQueue = [];
462464
}
463465

464466
if (obj && obj.postSend) {
465-
writeReq.oncomplete = obj.postSend.bind(null, handle);
466-
} else {
467-
writeReq.oncomplete = nop;
467+
req.oncomplete = obj.postSend.bind(null, handle);
468468
}
469469

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

620-
var err;
620+
var ex;
621621

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

631631
if (!callback) return;
632632

633-
if (err) {
634-
callback(err, stdout, stderr);
633+
if (ex) {
634+
callback(ex, stdout, stderr);
635635
} else if (code === 0 && signal === null) {
636636
callback(null, stdout, stderr);
637637
} else {
638-
var e = new Error('Command failed: ' + stderr);
639-
e.killed = child.killed || killed;
640-
e.code = code;
641-
e.signal = signal;
642-
callback(e, stdout, stderr);
638+
ex = new Error('Command failed: ' + stderr);
639+
ex.killed = child.killed || killed;
640+
ex.code = code < 0 ? uv.errname(code) : code;
641+
ex.signal = signal;
642+
callback(ex, stdout, stderr);
643643
}
644644
}
645645

646646
function errorhandler(e) {
647-
err = e;
647+
ex = e;
648648
child.stdout.destroy();
649649
child.stderr.destroy();
650650
exithandler();
@@ -658,7 +658,7 @@ exports.execFile = function(file /* args, options, callback */) {
658658
try {
659659
child.kill(options.killSignal);
660660
} catch (e) {
661-
err = e;
661+
ex = e;
662662
exithandler();
663663
}
664664
}
@@ -676,15 +676,15 @@ exports.execFile = function(file /* args, options, callback */) {
676676
child.stdout.addListener('data', function(chunk) {
677677
stdout += chunk;
678678
if (stdout.length > options.maxBuffer) {
679-
err = new Error('stdout maxBuffer exceeded.');
679+
ex = new Error('stdout maxBuffer exceeded.');
680680
kill();
681681
}
682682
});
683683

684684
child.stderr.addListener('data', function(chunk) {
685685
stderr += chunk;
686686
if (stderr.length > options.maxBuffer) {
687-
err = new Error('stderr maxBuffer exceeded.');
687+
ex = new Error('stderr maxBuffer exceeded.');
688688
kill();
689689
}
690690
});
@@ -767,9 +767,9 @@ function ChildProcess() {
767767
//
768768
// new in 0.9.x:
769769
//
770-
// - spawn failures are reported with exitCode == -1
770+
// - spawn failures are reported with exitCode < 0
771771
//
772-
var err = (exitCode == -1) ? errnoException(process._errno, 'spawn') : null;
772+
var err = (exitCode < 0) ? errnoException(exitCode, 'spawn') : null;
773773

774774
if (signalCode) {
775775
self.signalCode = signalCode;
@@ -784,7 +784,7 @@ function ChildProcess() {
784784
self._handle.close();
785785
self._handle = null;
786786

787-
if (exitCode == -1) {
787+
if (exitCode < 0) {
788788
self.emit('error', err);
789789
} else {
790790
self.emit('exit', self.exitCode, self.signalCode);
@@ -913,9 +913,9 @@ ChildProcess.prototype.spawn = function(options) {
913913
options.envPairs.push('NODE_CHANNEL_FD=' + ipcFd);
914914
}
915915

916-
var r = this._handle.spawn(options);
916+
var err = this._handle.spawn(options);
917917

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

926926
this._handle.close();
927927
this._handle = null;
928-
throw errnoException(process._errno, 'spawn');
928+
throw errnoException(err, 'spawn');
929929
}
930930

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

969-
return r;
969+
return err;
970970
};
971971

972972

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

992992
if (this._handle) {
993-
var r = this._handle.kill(signal);
994-
if (r == 0) {
993+
var err = this._handle.kill(signal);
994+
if (err === 0) {
995995
/* Success. */
996996
this.killed = true;
997997
return true;
998-
} else if (process._errno == 'ESRCH') {
998+
}
999+
if (err === uv.UV_ESRCH) {
9991000
/* Already dead. */
1000-
} else if (process._errno == 'EINVAL' || process._errno == 'ENOSYS') {
1001+
} else if (err === uv.UV_EINVAL || err === uv.UV_ENOSYS) {
10011002
/* The underlying platform doesn't support this signal. */
1002-
throw errnoException(process._errno, 'kill');
1003+
throw errnoException(err, 'kill');
10031004
} else {
10041005
/* Other error, almost certainly EPERM. */
1005-
this.emit('error', errnoException(process._errno, 'kill'));
1006+
this.emit('error', errnoException(err, 'kill'));
10061007
}
10071008
}
10081009

lib/cluster.js

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,20 @@ function SharedHandle(key, address, port, addressType, backlog, fd) {
5858
this.key = key;
5959
this.errno = '';
6060
this.workers = [];
61+
this.handle = null;
62+
this.errno = 0;
6163

64+
// FIXME(bnoordhuis) Polymorphic return type for lack of a better solution.
65+
var rval;
6266
if (addressType === 'udp4' || addressType === 'udp6')
63-
this.handle = dgram._createSocketHandle(address, port, addressType, fd);
67+
rval = dgram._createSocketHandle(address, port, addressType, fd);
6468
else
65-
this.handle = net._createServerHandle(address, port, addressType, fd);
69+
rval = net._createServerHandle(address, port, addressType, fd);
6670

67-
this.errno = this.handle ? '' : process._errno;
71+
if (typeof rval === 'number')
72+
this.errno = rval;
73+
else
74+
this.handle = rval;
6875
}
6976

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

117124
var self = this;
118125
function done() {
119-
if (self.handle.getsockname)
120-
send(null, { sockname: self.handle.getsockname() }, null);
121-
else
126+
if (self.handle.getsockname) {
127+
var out = {};
128+
var err = self.handle.getsockname(out);
129+
// TODO(bnoordhuis) Check err.
130+
send(null, { sockname: out }, null);
131+
}
132+
else {
122133
send(null, null, null); // UNIX socket.
134+
}
123135
self.handoff(worker); // In case there are connections pending.
124136
}
125137

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

146-
RoundRobinHandle.prototype.distribute = function(handle) {
158+
RoundRobinHandle.prototype.distribute = function(err, handle) {
147159
this.handles.push(handle);
148160
var worker = this.free.shift();
149161
if (worker) this.handoff(worker);
@@ -164,7 +176,7 @@ RoundRobinHandle.prototype.handoff = function(worker) {
164176
if (reply.accepted)
165177
handle.close();
166178
else
167-
self.distribute(handle); // Worker is shutting down. Send to another.
179+
self.distribute(0, handle); // Worker is shutting down. Send to another.
168180
self.handoff(worker);
169181
});
170182
};
@@ -476,8 +488,9 @@ function workerInit() {
476488

477489
function onerror(message, cb) {
478490
function listen(backlog) {
479-
process._errno = message.errno;
480-
return -1;
491+
// Translate 'EADDRINUSE' error back to numeric value. This function
492+
// is called as sock._handle.listen().
493+
return process.binding('uv')['UV_' + message.errno];
481494
}
482495
function close() {
483496
}
@@ -503,10 +516,8 @@ function workerInit() {
503516
delete handles[key];
504517
key = undefined;
505518
}
506-
function getsockname() {
507-
var rv = {};
508-
if (key) return util._extend(rv, message.sockname);
509-
return rv;
519+
function getsockname(out) {
520+
if (key) util._extend(out, message.sockname);
510521
}
511522
// Faux handle. Mimics a TCPWrap with just enough fidelity to get away
512523
// with it. Fools net.Server into thinking that it's backed by a real
@@ -530,7 +541,7 @@ function workerInit() {
530541
var server = handles[key];
531542
var accepted = (typeof server !== 'undefined');
532543
send({ ack: message.seq, accepted: accepted });
533-
if (accepted) server.onconnection(handle);
544+
if (accepted) server.onconnection(0, handle);
534545
}
535546

536547
Worker.prototype.disconnect = function() {

0 commit comments

Comments
 (0)