summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2013-07-18 23:18:50 +0200
committerBen Noordhuis <info@bnoordhuis.nl>2013-07-20 12:09:29 +0200
commitca9eb718fbf2cd2c60c7aeb3ca33413e17fcbbf0 (patch)
treeb9415d0e2f6005a651276cbc40d23196a8c02ddf /lib
parent0161ec87af3d71b10d8ce679c8a1a64358fae8dc (diff)
downloadandroid-node-v8-ca9eb718fbf2cd2c60c7aeb3ca33413e17fcbbf0.tar.gz
android-node-v8-ca9eb718fbf2cd2c60c7aeb3ca33413e17fcbbf0.tar.bz2
android-node-v8-ca9eb718fbf2cd2c60c7aeb3ca33413e17fcbbf0.zip
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().
Diffstat (limited to 'lib')
-rw-r--r--lib/child_process.js75
-rw-r--r--lib/cluster.js41
-rw-r--r--lib/dgram.js79
-rw-r--r--lib/dns.js65
-rw-r--r--lib/fs.js11
-rw-r--r--lib/net.js218
-rw-r--r--lib/tty.js12
7 files changed, 272 insertions, 229 deletions
diff --git a/lib/child_process.js b/lib/child_process.js
index b5b44bc379..1ca3d8ca75 100644
--- a/lib/child_process.js
+++ b/lib/child_process.js
@@ -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 = {};
@@ -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);
@@ -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. */
@@ -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;
@@ -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();
@@ -658,7 +658,7 @@ exports.execFile = function(file /* args, options, callback */) {
try {
child.kill(options.killSignal);
} catch (e) {
- err = e;
+ ex = e;
exithandler();
}
}
@@ -676,7 +676,7 @@ 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();
}
});
@@ -684,7 +684,7 @@ exports.execFile = function(file /* args, options, callback */) {
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();
}
});
@@ -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;
@@ -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);
@@ -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') {
@@ -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;
@@ -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;
};
@@ -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'));
}
}
diff --git a/lib/cluster.js b/lib/cluster.js
index 11ccbac5cd..b5859348e0 100644
--- a/lib/cluster.js
+++ b/lib/cluster.js
@@ -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) {
@@ -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.
}
@@ -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);
@@ -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);
});
};
@@ -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() {
}
@@ -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
@@ -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() {
diff --git a/lib/dgram.js b/lib/dgram.js
index 570cbbe8dd..7f279980cf 100644
--- a/lib/dgram.js
+++ b/lib/dgram.js
@@ -96,10 +96,10 @@ exports._createSocketHandle = function(address, port, addressType, fd) {
var handle = newHandle(addressType);
if (port || address) {
- var r = handle.bind(address, port || 0, 0);
- if (r == -1) {
+ var err = handle.bind(address, port || 0, 0);
+ if (err) {
handle.close();
- handle = null;
+ return err;
}
}
@@ -204,8 +204,9 @@ Socket.prototype.bind = function(/*port, address, callback*/) {
if (!self._handle)
return; // handle has been closed in the mean time
- if (self._handle.bind(ip, port || 0, /*flags=*/ 0)) {
- self.emit('error', errnoException(process._errno, 'bind'));
+ var err = self._handle.bind(ip, port || 0, /*flags=*/ 0);
+ if (err) {
+ self.emit('error', errnoException(err, 'bind'));
self._bindState = BIND_STATE_UNBOUND;
// Todo: close?
return;
@@ -276,22 +277,18 @@ Socket.prototype.send = function(buffer,
return;
}
- self._handle.lookup(address, function(err, ip) {
- if (err) {
- if (callback) callback(err);
- self.emit('error', err);
+ self._handle.lookup(address, function(ex, ip) {
+ if (ex) {
+ if (callback) callback(ex);
+ self.emit('error', ex);
}
else if (self._handle) {
- var req = self._handle.send(buffer, offset, length, port, ip);
- if (req) {
- req.oncomplete = afterSend;
- req.cb = callback;
- }
- else {
+ var req = { cb: callback, oncomplete: afterSend };
+ var err = self._handle.send(req, buffer, offset, length, port, ip);
+ if (err) {
// don't emit as error, dgram_legacy.js compatibility
- var err = errnoException(process._errno, 'send');
process.nextTick(function() {
- callback(err);
+ callback(errnoException(err, 'send'));
});
}
}
@@ -319,17 +316,20 @@ Socket.prototype.close = function() {
Socket.prototype.address = function() {
this._healthCheck();
- var address = this._handle.getsockname();
- if (!address)
- throw errnoException(process._errno, 'getsockname');
+ var out = {};
+ var err = this._handle.getsockname(out);
+ if (err) {
+ throw errnoException(err, 'getsockname');
+ }
- return address;
+ return out;
};
Socket.prototype.setBroadcast = function(arg) {
- if (this._handle.setBroadcast((arg) ? 1 : 0)) {
- throw errnoException(process._errno, 'setBroadcast');
+ var err = this._handle.setBroadcast(arg ? 1 : 0);
+ if (err) {
+ throw errnoException(err, 'setBroadcast');
}
};
@@ -339,8 +339,9 @@ Socket.prototype.setTTL = function(arg) {
throw new TypeError('Argument must be a number');
}
- if (this._handle.setTTL(arg)) {
- throw errnoException(process._errno, 'setTTL');
+ var err = this._handle.setTTL(arg);
+ if (err) {
+ throw errnoException(err, 'setTTL');
}
return arg;
@@ -352,8 +353,9 @@ Socket.prototype.setMulticastTTL = function(arg) {
throw new TypeError('Argument must be a number');
}
- if (this._handle.setMulticastTTL(arg)) {
- throw errnoException(process._errno, 'setMulticastTTL');
+ var err = this._handle.setMulticastTTL(arg);
+ if (err) {
+ throw errnoException(err, 'setMulticastTTL');
}
return arg;
@@ -361,10 +363,9 @@ Socket.prototype.setMulticastTTL = function(arg) {
Socket.prototype.setMulticastLoopback = function(arg) {
- arg = arg ? 1 : 0;
-
- if (this._handle.setMulticastLoopback(arg)) {
- throw errnoException(process._errno, 'setMulticastLoopback');
+ var err = this._handle.setMulticastLoopback(arg ? 1 : 0);
+ if (err) {
+ throw errnoException(err, 'setMulticastLoopback');
}
return arg; // 0.4 compatibility
@@ -379,8 +380,9 @@ Socket.prototype.addMembership = function(multicastAddress,
throw new Error('multicast address must be specified');
}
- if (this._handle.addMembership(multicastAddress, interfaceAddress)) {
- throw new errnoException(process._errno, 'addMembership');
+ var err = this._handle.addMembership(multicastAddress, interfaceAddress);
+ if (err) {
+ throw new errnoException(err, 'addMembership');
}
};
@@ -393,8 +395,9 @@ Socket.prototype.dropMembership = function(multicastAddress,
throw new Error('multicast address must be specified');
}
- if (this._handle.dropMembership(multicastAddress, interfaceAddress)) {
- throw new errnoException(process._errno, 'dropMembership');
+ var err = this._handle.dropMembership(multicastAddress, interfaceAddress);
+ if (err) {
+ throw new errnoException(err, 'dropMembership');
}
};
@@ -415,10 +418,10 @@ Socket.prototype._stopReceiving = function() {
};
-function onMessage(handle, buf, rinfo) {
+function onMessage(nread, handle, buf, rinfo) {
var self = handle.owner;
- if (!buf) {
- return self.emit('error', errnoException(process._errno, 'recvmsg'));
+ if (nread < 0) {
+ return self.emit('error', errnoException(nread, 'recvmsg'));
}
rinfo.size = buf.length; // compatibility
self.emit('message', buf, rinfo);
diff --git a/lib/dns.js b/lib/dns.js
index baac2b48d9..23bd758b34 100644
--- a/lib/dns.js
+++ b/lib/dns.js
@@ -19,14 +19,31 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
-var cares = process.binding('cares_wrap');
var net = require('net');
var util = require('util');
-var errnoException = util._errnoException;
+var cares = process.binding('cares_wrap');
+var uv = process.binding('uv');
+
var isIp = net.isIP;
+function errnoException(err, syscall) {
+ // FIXME(bnoordhuis) Remove this backwards compatibility shite and pass
+ // the true error to the user. ENOTFOUND is not even a proper POSIX error!
+ if (err === uv.UV_EAI_MEMORY ||
+ err === uv.UV_EAI_NODATA ||
+ err === uv.UV_EAI_NONAME) {
+ var ex = new Error(syscall + ' ENOTFOUND');
+ ex.code = 'ENOTFOUND';
+ ex.errno = 'ENOTFOUND';
+ ex.syscall = syscall;
+ return ex;
+ }
+ return util._errnoException(err, syscall);
+}
+
+
// c-ares invokes a callback either synchronously or asynchronously,
// but the dns API should always invoke a callback asynchronously.
//
@@ -98,28 +115,28 @@ exports.lookup = function(domain, family, callback) {
return {};
}
- function onanswer(addresses) {
- if (addresses) {
- if (family) {
- callback(null, addresses[0], family);
- } else {
- callback(null, addresses[0], addresses[0].indexOf(':') >= 0 ? 6 : 4);
- }
+ function onanswer(err, addresses) {
+ if (err) {
+ return callback(errnoException(err, 'getaddrinfo'));
+ }
+ if (family) {
+ callback(null, addresses[0], family);
} else {
- callback(errnoException(process._errno, 'getaddrinfo'));
+ callback(null, addresses[0], addresses[0].indexOf(':') >= 0 ? 6 : 4);
}
}
- var wrap = cares.getaddrinfo(domain, family);
+ var req = {};
+ var err = cares.getaddrinfo(req, domain, family);
- if (!wrap) {
- throw errnoException(process._errno, 'getaddrinfo');
+ if (err) {
+ throw errnoException(err, 'getaddrinfo');
}
- wrap.oncomplete = onanswer;
+ req.oncomplete = onanswer;
callback.immediately = true;
- return wrap;
+ return req;
};
@@ -127,22 +144,22 @@ function resolver(bindingName) {
var binding = cares[bindingName];
return function query(name, callback) {
- function onanswer(status, result) {
- if (!status) {
+ function onanswer(err, result) {
+ if (err)
+ callback(errnoException(err, bindingName));
+ else
callback(null, result);
- } else {
- callback(errnoException(process._errno, bindingName));
- }
}
callback = makeAsync(callback);
- var wrap = binding(name, onanswer);
- if (!wrap) {
- throw errnoException(process._errno, bindingName);
+ var req = {};
+ var err = binding(req, name, onanswer);
+ if (err) {
+ throw errnoException(err, bindingName);
}
callback.immediately = true;
- return wrap;
+ return req;
}
}
diff --git a/lib/fs.js b/lib/fs.js
index 01a3c4d5e9..39d31ca46f 100644
--- a/lib/fs.js
+++ b/lib/fs.js
@@ -1004,9 +1004,9 @@ function FSWatcher() {
this._handle.owner = this;
this._handle.onchange = function(status, event, filename) {
- if (status) {
+ if (status < 0) {
self._handle.close();
- self.emit('error', errnoException(process._errno, 'watch'));
+ self.emit('error', errnoException(status, 'watch'));
} else {
self.emit('change', event, filename);
}
@@ -1016,11 +1016,10 @@ util.inherits(FSWatcher, EventEmitter);
FSWatcher.prototype.start = function(filename, persistent) {
nullCheck(filename);
- var r = this._handle.start(pathModule._makeLong(filename), persistent);
-
- if (r) {
+ var err = this._handle.start(pathModule._makeLong(filename), persistent);
+ if (err) {
this._handle.close();
- throw errnoException(process._errno, 'watch');
+ throw errnoException(err, 'watch');
}
};
diff --git a/lib/net.js b/lib/net.js
index c970595b50..0b250aeb6e 100644
--- a/lib/net.js
+++ b/lib/net.js
@@ -25,6 +25,7 @@ var timers = require('timers');
var util = require('util');
var assert = require('assert');
var cares = process.binding('cares_wrap');
+var uv = process.binding('uv');
var cluster;
var errnoException = util._errnoException;
@@ -206,12 +207,11 @@ function onSocketFinish() {
if (!this._handle || !this._handle.shutdown)
return this.destroy();
- var shutdownReq = this._handle.shutdown();
+ var req = { oncomplete: afterShutdown };
+ var err = this._handle.shutdown(req);
- if (!shutdownReq)
- return this._destroy(errnoException(process._errno, 'shutdown'));
-
- shutdownReq.oncomplete = afterShutdown;
+ if (err)
+ return this._destroy(errnoException(err, 'shutdown'));
}
@@ -338,7 +338,10 @@ Socket.prototype.setKeepAlive = function(setting, msecs) {
Socket.prototype.address = function() {
if (this._handle && this._handle.getsockname) {
- return this._handle.getsockname();
+ var out = {};
+ var err = this._handle.getsockname(out);
+ // TODO(bnoordhuis) Check err and throw?
+ return out;
}
return null;
};
@@ -381,9 +384,9 @@ Socket.prototype._read = function(n) {
// not already reading, start the flow
debug('Socket._read readStart');
this._handle.reading = true;
- var r = this._handle.readStart();
- if (r)
- this._destroy(errnoException(process._errno, 'read'));
+ var err = this._handle.readStart();
+ if (err)
+ this._destroy(errnoException(err, 'read'));
}
};
@@ -486,17 +489,16 @@ Socket.prototype.destroy = function(exception) {
// This function is called whenever the handle gets a
// buffer, or when there's an error reading.
-function onread(buffer) {
+function onread(nread, buffer) {
var handle = this;
var self = handle.owner;
- var length = !!buffer ? buffer.length : 0;
assert(handle === self._handle, 'handle != self._handle');
timers._unrefActive(self);
- debug('onread', process._errno, length);
+ debug('onread', nread);
- if (buffer) {
+ if (nread > 0) {
debug('got data');
// read success.
@@ -504,16 +506,9 @@ function onread(buffer) {
// will prevent this from being called again until _read() gets
// called again.
- // if we didn't get any bytes, that doesn't necessarily mean EOF.
- // wait for the next one.
- if (length === 0) {
- debug('not any data, keep waiting');
- return;
- }
-
// if it's not enough data, we'll just call handle.readStart()
// again right away.
- self.bytesRead += length;
+ self.bytesRead += nread;
// Optimization: emit the original buffer with end points
var ret = true;
@@ -523,33 +518,41 @@ function onread(buffer) {
if (handle.reading && !ret) {
handle.reading = false;
debug('readStop');
- var r = handle.readStop();
- if (r)
- self._destroy(errnoException(process._errno, 'read'));
+ var err = handle.readStop();
+ if (err)
+ self._destroy(errnoException(err, 'read'));
}
+ return;
+ }
- } else if (process._errno == 'EOF') {
- debug('EOF');
-
- if (self._readableState.length === 0) {
- self.readable = false;
- maybeDestroy(self);
- }
+ // if we didn't get any bytes, that doesn't necessarily mean EOF.
+ // wait for the next one.
+ if (nread === 0) {
+ debug('not any data, keep waiting');
+ return;
+ }
- if (self.onend) self.once('end', self.onend);
+ // Error, possibly EOF.
+ if (nread !== uv.UV_EOF) {
+ return self._destroy(errnoException(nread, 'read'));
+ }
- // push a null to signal the end of data.
- self.push(null);
+ debug('EOF');
- // internal end event so that we know that the actual socket
- // is no longer readable, and we can start the shutdown
- // procedure. No need to wait for all the data to be consumed.
- self.emit('_socketEnd');
- } else {
- debug('error', process._errno);
- // Error
- self._destroy(errnoException(process._errno, 'read'));
+ if (self._readableState.length === 0) {
+ self.readable = false;
+ maybeDestroy(self);
}
+
+ if (self.onend) self.once('end', self.onend);
+
+ // push a null to signal the end of data.
+ self.push(null);
+
+ // internal end event so that we know that the actual socket
+ // is no longer readable, and we can start the shutdown
+ // procedure. No need to wait for all the data to be consumed.
+ self.emit('_socketEnd');
}
@@ -558,10 +561,10 @@ Socket.prototype._getpeername = function() {
return {};
}
if (!this._peername) {
- this._peername = this._handle.getpeername();
- if (!this._peername) {
- return {};
- }
+ var out = {};
+ var err = this._handle.getpeername(out);
+ if (err) return {}; // FIXME(bnoordhuis) Throw?
+ this._peername = out;
}
return this._peername;
};
@@ -582,10 +585,10 @@ Socket.prototype._getsockname = function() {
return {};
}
if (!this._sockname) {
- this._sockname = this._handle.getsockname();
- if (!this._sockname) {
- return {};
- }
+ var out = {};
+ var err = this._handle.getsockname(out);
+ if (err) return {}; // FIXME(bnoordhuis) Throw?
+ this._sockname = out;
}
return this._sockname;
};
@@ -630,7 +633,9 @@ Socket.prototype._writeGeneric = function(writev, data, encoding, cb) {
return false;
}
- var writeReq;
+ var req = { oncomplete: afterWrite };
+ var err;
+
if (writev) {
var chunks = new Array(data.length << 1);
for (var i = 0; i < data.length; i++) {
@@ -640,28 +645,26 @@ Socket.prototype._writeGeneric = function(writev, data, encoding, cb) {
chunks[i * 2] = chunk;
chunks[i * 2 + 1] = enc;
}
- var writeReq = this._handle.writev(chunks);
+ err = this._handle.writev(req, chunks);
// Retain chunks
- if (writeReq)
- writeReq._chunks = chunks;
+ if (err === 0) req._chunks = chunks;
} else {
var enc = Buffer.isBuffer(data) ? 'buffer' : encoding;
- var writeReq = createWriteReq(this._handle, data, enc);
+ err = createWriteReq(req, this._handle, data, enc);
}
- if (!writeReq)
- return this._destroy(errnoException(process._errno, 'write'), cb);
+ if (err)
+ return this._destroy(errnoException(err, 'write'), cb);
- writeReq.oncomplete = afterWrite;
- this._bytesDispatched += writeReq.bytes;
+ this._bytesDispatched += req.bytes;
// If it was entirely flushed, we can write some more right now.
// However, if more is left in the queue, then wait until that clears.
if (this._handle.writeQueueSize === 0)
cb();
else
- writeReq.cb = cb;
+ req.cb = cb;
};
@@ -698,26 +701,26 @@ function getEncodingId(encoding) {
}
}
-function createWriteReq(handle, data, encoding) {
+function createWriteReq(req, handle, data, encoding) {
switch (encoding) {
case 'buffer':
- return handle.writeBuffer(data);
+ return handle.writeBuffer(req, data);
case 'utf8':
case 'utf-8':
- return handle.writeUtf8String(data);
+ return handle.writeUtf8String(req, data);
case 'ascii':
- return handle.writeAsciiString(data);
+ return handle.writeAsciiString(req, data);
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
- return handle.writeUcs2String(data);
+ return handle.writeUcs2String(req, data);
default:
- return handle.writeBuffer(new Buffer(data, encoding));
+ return handle.writeBuffer(req, new Buffer(data, encoding));
}
}
@@ -758,9 +761,10 @@ function afterWrite(status, handle, req) {
return;
}
- if (status) {
- debug('write failure', errnoException(process._errno, 'write'));
- self._destroy(errnoException(process._errno, 'write'), req.cb);
+ if (status < 0) {
+ var ex = errnoException(status, 'write');
+ debug('write failure', ex);
+ self._destroy(ex, req.cb);
return;
}
@@ -780,33 +784,31 @@ function connect(self, address, port, addressType, localAddress) {
assert.ok(self._connecting);
+ var err;
if (localAddress) {
- var r;
if (addressType == 6) {
- r = self._handle.bind6(localAddress);
+ err = self._handle.bind6(localAddress);
} else {
- r = self._handle.bind(localAddress);
+ err = self._handle.bind(localAddress);
}
- if (r) {
- self._destroy(errnoException(process._errno, 'bind'));
+ if (err) {
+ self._destroy(errnoException(err, 'bind'));
return;
}
}
- var connectReq;
+ var req = { oncomplete: afterConnect };
if (addressType == 6) {
- connectReq = self._handle.connect6(address, port);
+ err = self._handle.connect6(req, address, port);
} else if (addressType == 4) {
- connectReq = self._handle.connect(address, port);
+ err = self._handle.connect(req, address, port);
} else {
- connectReq = self._handle.connect(address, afterConnect);
+ err = self._handle.connect(req, address, afterConnect);
}
- if (connectReq !== null) {
- connectReq.oncomplete = afterConnect;
- } else {
- self._destroy(errnoException(process._errno, 'connect'));
+ if (err) {
+ self._destroy(errnoException(err, 'connect'));
}
}
@@ -937,7 +939,7 @@ function afterConnect(status, handle, req, readable, writable) {
} else {
self._connecting = false;
- self._destroy(errnoException(process._errno, 'connect'));
+ self._destroy(errnoException(status, 'connect'));
}
}
@@ -992,7 +994,7 @@ function toNumber(x) { return (x = Number(x)) >= 0 ? x : false; }
var createServerHandle = exports._createServerHandle =
function(address, port, addressType, fd) {
- var r = 0;
+ var err = 0;
// assign handle in listen, and clean up if bind or listen fails
var handle;
@@ -1003,8 +1005,7 @@ var createServerHandle = exports._createServerHandle =
catch (e) {
// Not a fd we can listen on. This will trigger an error.
debug('listen invalid fd=' + fd + ': ' + e.message);
- process._errno = 'EINVAL'; // hack, callers expect that errno is set
- return null;
+ return uv.UV_EINVAL;
}
handle.open(fd);
handle.readable = true;
@@ -1026,15 +1027,15 @@ var createServerHandle = exports._createServerHandle =
if (address || port) {
debug('bind to ' + address);
if (addressType == 6) {
- r = handle.bind6(address, port);
+ err = handle.bind6(address, port);
} else {
- r = handle.bind(address, port);
+ err = handle.bind(address, port);
}
}
- if (r) {
+ if (err) {
handle.close();
- handle = null;
+ return err;
}
return handle;
@@ -1044,20 +1045,20 @@ var createServerHandle = exports._createServerHandle =
Server.prototype._listen2 = function(address, port, addressType, backlog, fd) {
debug('listen2', address, port, addressType, backlog);
var self = this;
- var r = 0;
// If there is not yet a handle, we need to create one and bind.
// In the case of a server sent via IPC, we don't need to do this.
if (!self._handle) {
debug('_listen2: create a handle');
- self._handle = createServerHandle(address, port, addressType, fd);
- if (!self._handle) {
- var error = errnoException(process._errno, 'listen');
+ var rval = createServerHandle(address, port, addressType, fd);
+ if (typeof rval === 'number') {
+ var error = errnoException(rval, 'listen');
process.nextTick(function() {
self.emit('error', error);
});
return;
}
+ self._handle = rval;
} else {
debug('_listen2: have a handle already');
}
@@ -1068,10 +1069,10 @@ Server.prototype._listen2 = function(address, port, addressType, backlog, fd) {
// Use a backlog of 512 entries. We pass 511 to the listen() call because
// the kernel does: backlogsize = roundup_pow_of_two(backlogsize + 1);
// which will thus give us a backlog of 512 entries.
- r = self._handle.listen(backlog || 511);
+ var err = self._handle.listen(backlog || 511);
- if (r) {
- var ex = errnoException(process._errno, 'listen');
+ if (err) {
+ var ex = errnoException(err, 'listen');
self._handle.close();
self._handle = null;
process.nextTick(function() {
@@ -1104,9 +1105,15 @@ function listen(self, address, port, addressType, backlog, fd) {
// not actually bound. That's why we check if the actual port matches what
// we requested and if not, raise an error. The exception is when port == 0
// because that means "any random port".
- if (port && handle.getsockname && port != handle.getsockname().port) {
- self.emit('error', errnoException('EADDRINUSE', 'bind'));
- return;
+ if (port && handle.getsockname) {
+ var out = {};
+ var err = handle.getsockname(out);
+ if (err === 0 && port !== out.port) {
+ err = uv.UV_EADDRINUSE;
+ }
+ if (err) {
+ return self.emit('error', errnoException(err, 'bind'));
+ }
}
self._handle = handle;
@@ -1176,7 +1183,10 @@ Server.prototype.listen = function() {
Server.prototype.address = function() {
if (this._handle && this._handle.getsockname) {
- return this._handle.getsockname();
+ var out = {};
+ var err = this._handle.getsockname(out);
+ // TODO(bnoordhuis) Check err and throw?
+ return out;
} else if (this._pipeName) {
return this._pipeName;
} else {
@@ -1184,14 +1194,14 @@ Server.prototype.address = function() {
}
};
-function onconnection(clientHandle) {
+function onconnection(err, clientHandle) {
var handle = this;
var self = handle.owner;
debug('onconnection');
- if (!clientHandle) {
- self.emit('error', errnoException(process._errno, 'accept'));
+ if (err) {
+ self.emit('error', errnoException(err, 'accept'));
return;
}
diff --git a/lib/tty.js b/lib/tty.js
index 5d60ec6608..5c854edf09 100644
--- a/lib/tty.js
+++ b/lib/tty.js
@@ -79,8 +79,9 @@ function WriteStream(fd) {
writable: true
});
- var winSize = this._handle.getWindowSize();
- if (winSize) {
+ var winSize = [];
+ var err = this._handle.getWindowSize(winSize);
+ if (!err) {
this.columns = winSize[0];
this.rows = winSize[1];
}
@@ -95,9 +96,10 @@ WriteStream.prototype.isTTY = true;
WriteStream.prototype._refreshSize = function() {
var oldCols = this.columns;
var oldRows = this.rows;
- var winSize = this._handle.getWindowSize();
- if (!winSize) {
- this.emit('error', errnoException(process._errno, 'getWindowSize'));
+ var winSize = [];
+ var err = this._handle.getWindowSize(winSize);
+ if (err) {
+ this.emit('error', errnoException(err, 'getWindowSize'));
return;
}
var newCols = winSize[0];