diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2013-07-18 23:18:50 +0200 |
---|---|---|
committer | Ben Noordhuis <info@bnoordhuis.nl> | 2013-07-20 12:09:29 +0200 |
commit | ca9eb718fbf2cd2c60c7aeb3ca33413e17fcbbf0 (patch) | |
tree | b9415d0e2f6005a651276cbc40d23196a8c02ddf /lib | |
parent | 0161ec87af3d71b10d8ce679c8a1a64358fae8dc (diff) | |
download | android-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.js | 75 | ||||
-rw-r--r-- | lib/cluster.js | 41 | ||||
-rw-r--r-- | lib/dgram.js | 79 | ||||
-rw-r--r-- | lib/dns.js | 65 | ||||
-rw-r--r-- | lib/fs.js | 11 | ||||
-rw-r--r-- | lib/net.js | 218 | ||||
-rw-r--r-- | lib/tty.js | 12 |
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; } } @@ -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]; |