From ca9eb718fbf2cd2c60c7aeb3ca33413e17fcbbf0 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Thu, 18 Jul 2013 23:18:50 +0200 Subject: [PATCH] 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(). --- lib/child_process.js | 75 +++++------ lib/cluster.js | 41 +++--- lib/dgram.js | 79 ++++++------ lib/dns.js | 65 ++++++---- lib/fs.js | 11 +- lib/net.js | 218 ++++++++++++++++---------------- lib/tty.js | 12 +- src/cares_wrap.cc | 260 +++++++++++++++++++-------------------- src/fs_event_wrap.cc | 13 +- src/node.cc | 70 +++-------- src/node.h | 2 - src/node.js | 16 +-- src/node_file.cc | 32 ++--- src/node_os.cc | 15 ++- src/node_stat_watcher.cc | 3 - src/pipe_wrap.cc | 44 +++---- src/process_wrap.cc | 20 +-- src/signal_wrap.cc | 10 +- src/stream_wrap.cc | 183 ++++++++++++--------------- src/stream_wrap.h | 3 +- src/tcp_wrap.cc | 141 +++++++++++---------- src/timer_wrap.cc | 16 +-- src/tls_wrap.cc | 14 +-- src/tty_wrap.cc | 21 ++-- src/udp_wrap.cc | 142 +++++++++++---------- 25 files changed, 725 insertions(+), 781 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]; diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index 4a55453f69..91d5b8c86c 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -228,56 +228,11 @@ static Local HostentToNames(struct hostent* host) { } -static const char* AresErrnoString(int errorno) { - switch (errorno) { -#define ERRNO_CASE(e) case ARES_##e: return #e; - ERRNO_CASE(SUCCESS) - ERRNO_CASE(ENODATA) - ERRNO_CASE(EFORMERR) - ERRNO_CASE(ESERVFAIL) - ERRNO_CASE(ENOTFOUND) - ERRNO_CASE(ENOTIMP) - ERRNO_CASE(EREFUSED) - ERRNO_CASE(EBADQUERY) - ERRNO_CASE(EBADNAME) - ERRNO_CASE(EBADFAMILY) - ERRNO_CASE(EBADRESP) - ERRNO_CASE(ECONNREFUSED) - ERRNO_CASE(ETIMEOUT) - ERRNO_CASE(EOF) - ERRNO_CASE(EFILE) - ERRNO_CASE(ENOMEM) - ERRNO_CASE(EDESTRUCTION) - ERRNO_CASE(EBADSTR) - ERRNO_CASE(EBADFLAGS) - ERRNO_CASE(ENONAME) - ERRNO_CASE(EBADHINTS) - ERRNO_CASE(ENOTINITIALIZED) - ERRNO_CASE(ELOADIPHLPAPI) - ERRNO_CASE(EADDRGETNETWORKPARAMS) - ERRNO_CASE(ECANCELLED) -#undef ERRNO_CASE - default: - assert(0 && "Unhandled c-ares error"); - return "(UNKNOWN)"; - } -} - - -static void SetAresErrno(int errorno) { - HandleScope scope(node_isolate); - Local key = String::NewSymbol("_errno"); - Local value = String::NewSymbol(AresErrnoString(errorno)); - Local process = PersistentToLocal(process_p); - process->Set(key, value); -} - - class QueryWrap { public: - QueryWrap() { + QueryWrap(Local req_wrap_obj) { HandleScope scope(node_isolate); - persistent().Reset(node_isolate, Object::New()); + persistent().Reset(node_isolate, req_wrap_obj); } virtual ~QueryWrap() { @@ -355,10 +310,10 @@ class QueryWrap { void ParseError(int status) { assert(status != ARES_SUCCESS); - SetAresErrno(status); - HandleScope scope(node_isolate); - Local argv[1] = { Integer::New(-1, node_isolate) }; + Local argv[] = { + Integer::New(status, node_isolate) + }; MakeCallback(object(), oncomplete_sym, ARRAY_SIZE(argv), argv); } @@ -378,6 +333,9 @@ class QueryWrap { class QueryAWrap: public QueryWrap { public: + QueryAWrap(Local req_wrap_obj) : QueryWrap(req_wrap_obj) { + } + int Send(const char* name) { ares_query(ares_channel, name, ns_c_in, ns_t_a, Callback, GetQueryArg()); return 0; @@ -405,6 +363,9 @@ class QueryAWrap: public QueryWrap { class QueryAaaaWrap: public QueryWrap { public: + QueryAaaaWrap(Local req_wrap_obj) : QueryWrap(req_wrap_obj) { + } + int Send(const char* name) { ares_query(ares_channel, name, @@ -437,6 +398,9 @@ class QueryAaaaWrap: public QueryWrap { class QueryCnameWrap: public QueryWrap { public: + QueryCnameWrap(Local req_wrap_obj) : QueryWrap(req_wrap_obj) { + } + int Send(const char* name) { ares_query(ares_channel, name, @@ -472,6 +436,9 @@ class QueryCnameWrap: public QueryWrap { class QueryMxWrap: public QueryWrap { public: + QueryMxWrap(Local req_wrap_obj) : QueryWrap(req_wrap_obj) { + } + int Send(const char* name) { ares_query(ares_channel, name, ns_c_in, ns_t_mx, Callback, GetQueryArg()); return 0; @@ -511,6 +478,9 @@ class QueryMxWrap: public QueryWrap { class QueryNsWrap: public QueryWrap { public: + QueryNsWrap(Local req_wrap_obj) : QueryWrap(req_wrap_obj) { + } + int Send(const char* name) { ares_query(ares_channel, name, ns_c_in, ns_t_ns, Callback, GetQueryArg()); return 0; @@ -536,6 +506,9 @@ class QueryNsWrap: public QueryWrap { class QueryTxtWrap: public QueryWrap { public: + QueryTxtWrap(Local req_wrap_obj) : QueryWrap(req_wrap_obj) { + } + int Send(const char* name) { ares_query(ares_channel, name, ns_c_in, ns_t_txt, Callback, GetQueryArg()); return 0; @@ -568,6 +541,9 @@ class QueryTxtWrap: public QueryWrap { class QuerySrvWrap: public QueryWrap { public: + QuerySrvWrap(Local req_wrap_obj) : QueryWrap(req_wrap_obj) { + } + int Send(const char* name) { ares_query(ares_channel, name, @@ -617,6 +593,9 @@ class QuerySrvWrap: public QueryWrap { class QueryNaptrWrap: public QueryWrap { public: + QueryNaptrWrap(Local req_wrap_obj) : QueryWrap(req_wrap_obj) { + } + int Send(const char* name) { ares_query(ares_channel, name, @@ -679,18 +658,21 @@ class QueryNaptrWrap: public QueryWrap { class GetHostByAddrWrap: public QueryWrap { public: + GetHostByAddrWrap(Local req_wrap_obj) : QueryWrap(req_wrap_obj) { + } + int Send(const char* name) { int length, family; char address_buffer[sizeof(struct in6_addr)]; - if (uv_inet_pton(AF_INET, name, &address_buffer).code == UV_OK) { + if (uv_inet_pton(AF_INET, name, &address_buffer) == 0) { length = sizeof(struct in_addr); family = AF_INET; - } else if (uv_inet_pton(AF_INET6, name, &address_buffer).code == UV_OK) { + } else if (uv_inet_pton(AF_INET6, name, &address_buffer) == 0) { length = sizeof(struct in6_addr); family = AF_INET6; } else { - return ARES_ENOTIMP; + return UV_EINVAL; // So errnoException() reports a proper error. } ares_gethostbyaddr(ares_channel, @@ -713,6 +695,9 @@ class GetHostByAddrWrap: public QueryWrap { class GetHostByNameWrap: public QueryWrap { public: + GetHostByNameWrap(Local req_wrap_obj) : QueryWrap(req_wrap_obj) { + } + int Send(const char* name, int family) { ares_gethostbyname(ares_channel, name, family, Callback, GetQueryArg()); return 0; @@ -735,26 +720,27 @@ static void Query(const FunctionCallbackInfo& args) { HandleScope scope(node_isolate); assert(!args.IsConstructCall()); - assert(args.Length() >= 2); - assert(args[1]->IsFunction()); + assert(args[0]->IsObject()); + assert(args[1]->IsString()); + assert(args[2]->IsFunction()); - Wrap* wrap = new Wrap(); - wrap->SetOnComplete(args[1]); + Local req_wrap_obj = args[0].As(); + Local string = args[1].As(); + Local callback = args[2].As(); + + Wrap* wrap = new Wrap(req_wrap_obj); + wrap->SetOnComplete(callback); // We must cache the wrap's js object here, because cares might make the // callback from the wrap->Send stack. This will destroy the wrap's internal // object reference, causing wrap->object() to return an empty handle. Local object = Local::New(node_isolate, wrap->persistent()); - String::Utf8Value name(args[0]); + String::Utf8Value name(string); + int err = wrap->Send(*name); + if (err) delete wrap; - int r = wrap->Send(*name); - if (r) { - SetAresErrno(r); - delete wrap; - } else { - args.GetReturnValue().Set(object); - } + args.GetReturnValue().Set(err); } @@ -763,27 +749,29 @@ static void QueryWithFamily(const FunctionCallbackInfo& args) { HandleScope scope(node_isolate); assert(!args.IsConstructCall()); - assert(args.Length() >= 3); - assert(args[2]->IsFunction()); + assert(args[0]->IsObject()); + assert(args[1]->IsString()); + assert(args[2]->IsInt32()); + assert(args[3]->IsFunction()); + + Local req_wrap_obj = args[0].As(); + Local string = args[1].As(); + int family = args[2]->Int32Value(); + Local callback = args[3].As(); - Wrap* wrap = new Wrap(); - wrap->SetOnComplete(args[2]); + Wrap* wrap = new Wrap(req_wrap_obj); + wrap->SetOnComplete(callback); // We must cache the wrap's js object here, because cares might make the // callback from the wrap->Send stack. This will destroy the wrap's internal // object reference, causing wrap->object() to return an empty handle. Local object = Local::New(node_isolate, wrap->persistent()); - String::Utf8Value name(args[0]); - int family = args[1]->Int32Value(); + String::Utf8Value name(string); + int err = wrap->Send(*name, family); + if (err) delete wrap; - int r = wrap->Send(*name, family); - if (r) { - SetAresErrno(r); - delete wrap; - } else { - args.GetReturnValue().Set(object); - } + args.GetReturnValue().Set(err); } @@ -792,13 +780,12 @@ void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) { GetAddrInfoReqWrap* req_wrap = (GetAddrInfoReqWrap*) req->data; - Local argv[1]; + Local argv[] = { + Integer::New(status, node_isolate), + Null(node_isolate) + }; - if (status) { - // Error - SetErrno(uv_last_error(uv_default_loop())); - argv[0] = Null(node_isolate); - } else { + if (status == 0) { // Success struct addrinfo *address; int n = 0; @@ -826,11 +813,11 @@ void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) { if (address->ai_family == AF_INET) { // Juggle pointers addr = (char*) &((struct sockaddr_in*) address->ai_addr)->sin_addr; - uv_err_t err = uv_inet_ntop(address->ai_family, - addr, - ip, - INET6_ADDRSTRLEN); - if (err.code != UV_OK) + int err = uv_inet_ntop(address->ai_family, + addr, + ip, + INET6_ADDRSTRLEN); + if (err) continue; // Create JavaScript string @@ -852,11 +839,11 @@ void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) { if (address->ai_family == AF_INET6) { // Juggle pointers addr = (char*) &((struct sockaddr_in6*) address->ai_addr)->sin6_addr; - uv_err_t err = uv_inet_ntop(address->ai_family, - addr, - ip, - INET6_ADDRSTRLEN); - if (err.code != UV_OK) + int err = uv_inet_ntop(address->ai_family, + addr, + ip, + INET6_ADDRSTRLEN); + if (err) continue; // Create JavaScript string @@ -870,7 +857,7 @@ void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) { } - argv[0] = results; + argv[1] = results; } uv_freeaddrinfo(res); @@ -889,9 +876,9 @@ static void IsIP(const FunctionCallbackInfo& args) { char address_buffer[sizeof(struct in6_addr)]; int rc = 0; - if (uv_inet_pton(AF_INET, *ip, &address_buffer).code == UV_OK) + if (uv_inet_pton(AF_INET, *ip, &address_buffer) == 0) rc = 4; - else if (uv_inet_pton(AF_INET6, *ip, &address_buffer).code == UV_OK) + else if (uv_inet_pton(AF_INET6, *ip, &address_buffer) == 0) rc = 6; args.GetReturnValue().Set(rc); @@ -901,42 +888,45 @@ static void IsIP(const FunctionCallbackInfo& args) { static void GetAddrInfo(const FunctionCallbackInfo& args) { HandleScope scope(node_isolate); - String::Utf8Value hostname(args[0]); - - int fam = AF_UNSPEC; - if (args[1]->IsInt32()) { - switch (args[1]->Int32Value()) { - case 6: - fam = AF_INET6; - break; - - case 4: - fam = AF_INET; - break; - } + assert(args[0]->IsObject()); + assert(args[1]->IsString()); + assert(args[2]->IsInt32()); + Local req_wrap_obj = args[0].As(); + String::Utf8Value hostname(args[1]); + + int family; + switch (args[2]->Int32Value()) { + case 0: + family = AF_UNSPEC; + break; + case 4: + family = AF_INET; + break; + case 6: + family = AF_INET6; + break; + default: + assert(0 && "bad address family"); + abort(); } - GetAddrInfoReqWrap* req_wrap = new GetAddrInfoReqWrap(); + GetAddrInfoReqWrap* req_wrap = new GetAddrInfoReqWrap(req_wrap_obj); struct addrinfo hints; memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = fam; + hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; - int r = uv_getaddrinfo(uv_default_loop(), - &req_wrap->req_, - AfterGetAddrInfo, - *hostname, - NULL, - &hints); + int err = uv_getaddrinfo(uv_default_loop(), + &req_wrap->req_, + AfterGetAddrInfo, + *hostname, + NULL, + &hints); req_wrap->Dispatched(); + if (err) delete req_wrap; - if (r) { - SetErrno(uv_last_error(uv_default_loop())); - delete req_wrap; - } else { - args.GetReturnValue().Set(req_wrap->persistent()); - } + args.GetReturnValue().Set(err); } @@ -956,8 +946,8 @@ static void GetServers(const FunctionCallbackInfo& args) { char ip[INET6_ADDRSTRLEN]; const void* caddr = static_cast(&cur->addr); - uv_err_t err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip)); - assert(err.code == UV_OK); + int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip)); + assert(err == 0); Local addr = String::New(ip); server_array->Set(i, addr); @@ -986,7 +976,7 @@ static void SetServers(const FunctionCallbackInfo& args) { ares_addr_node* servers = new ares_addr_node[len]; ares_addr_node* last = NULL; - uv_err_t uv_ret; + int err; for (uint32_t i = 0; i < len; i++) { assert(arr->Get(i)->IsArray()); @@ -1004,18 +994,18 @@ static void SetServers(const FunctionCallbackInfo& args) { switch (fam) { case 4: cur->family = AF_INET; - uv_ret = uv_inet_pton(AF_INET, *ip, &cur->addr); + err = uv_inet_pton(AF_INET, *ip, &cur->addr); break; case 6: cur->family = AF_INET6; - uv_ret = uv_inet_pton(AF_INET6, *ip, &cur->addr); + err = uv_inet_pton(AF_INET6, *ip, &cur->addr); break; default: assert(0 && "Bad address family."); abort(); } - if (uv_ret.code != UV_OK) + if (err) break; cur->next = NULL; @@ -1026,16 +1016,14 @@ static void SetServers(const FunctionCallbackInfo& args) { last = cur; } - int r; - - if (uv_ret.code == UV_OK) - r = ares_set_servers(ares_channel, &servers[0]); + if (err == 0) + err = ares_set_servers(ares_channel, &servers[0]); else - r = ARES_EBADSTR; + err = ARES_EBADSTR; delete[] servers; - args.GetReturnValue().Set(r); + args.GetReturnValue().Set(err); } diff --git a/src/fs_event_wrap.cc b/src/fs_event_wrap.cc index bcac8dbab8..d33308b4db 100644 --- a/src/fs_event_wrap.cc +++ b/src/fs_event_wrap.cc @@ -108,18 +108,20 @@ void FSEventWrap::Start(const FunctionCallbackInfo& args) { String::Utf8Value path(args[0]); - int r = uv_fs_event_init(uv_default_loop(), &wrap->handle_, *path, OnEvent, 0); - if (r == 0) { + int err = uv_fs_event_init(uv_default_loop(), + &wrap->handle_, + *path, + OnEvent, + 0); + if (err == 0) { // Check for persistent argument if (!args[1]->IsTrue()) { uv_unref(reinterpret_cast(&wrap->handle_)); } wrap->initialized_ = true; - } else { - SetErrno(uv_last_error(uv_default_loop())); } - args.GetReturnValue().Set(r); + args.GetReturnValue().Set(err); } @@ -144,7 +146,6 @@ void FSEventWrap::OnEvent(uv_fs_event_t* handle, const char* filename, // assumption that a rename implicitly means an attribute change. Not too // unreasonable, right? Still, we should revisit this before v1.0. if (status) { - SetErrno(uv_last_error(uv_default_loop())); eventStr = String::Empty(node_isolate); } else if (events & UV_RENAME) { diff --git a/src/node.cc b/src/node.cc index b4c3da7df2..d14a6c631b 100644 --- a/src/node.cc +++ b/src/node.cc @@ -774,22 +774,6 @@ Local ErrnoException(int errorno, } -static const char* get_uv_errno_string(int errorno) { - uv_err_t err; - memset(&err, 0, sizeof err); - err.code = (uv_err_code)errorno; - return uv_err_name(err); -} - - -static const char* get_uv_errno_message(int errorno) { - uv_err_t err; - memset(&err, 0, sizeof err); - err.code = (uv_err_code)errorno; - return uv_strerror(err); -} - - // hack alert! copy of ErrnoException, tuned for uv errors Local UVException(int errorno, const char *syscall, @@ -803,9 +787,9 @@ Local UVException(int errorno, } if (!msg || !msg[0]) - msg = get_uv_errno_message(errorno); + msg = uv_strerror(errorno); - Local estring = String::NewSymbol(get_uv_errno_string(errorno)); + Local estring = String::NewSymbol(uv_err_name(errorno)); Local message = String::NewSymbol(msg); Local cons1 = String::Concat(estring, String::NewSymbol(", ")); Local cons2 = String::Concat(cons1, message); @@ -1080,25 +1064,6 @@ MakeCallback(const Handle object, } -void SetErrno(uv_err_t err) { - HandleScope scope(node_isolate); - Local process = PersistentToLocal(process_p); - - static Cached errno_symbol; - if (errno_symbol.IsEmpty()) { - errno_symbol = String::New("_errno"); - } - - if (err.code == UV_UNKNOWN) { - char errno_buf[100]; - snprintf(errno_buf, 100, "Unknown system errno %d", err.sys_errno_); - process->Set(errno_symbol, String::New(errno_buf)); - } else { - process->Set(errno_symbol, String::NewSymbol(uv_err_name(err))); - } -} - - enum encoding ParseEncoding(Handle encoding_v, enum encoding _default) { HandleScope scope(node_isolate); @@ -1356,11 +1321,9 @@ static void Chdir(const FunctionCallbackInfo& args) { } String::Utf8Value path(args[0]); - - uv_err_t r = uv_chdir(*path); - - if (r.code != UV_OK) { - return ThrowUVException(r.code, "uv_chdir"); + int err = uv_chdir(*path); + if (err) { + return ThrowUVException(err, "uv_chdir"); } } @@ -1374,9 +1337,9 @@ static void Cwd(const FunctionCallbackInfo& args) { char buf[PATH_MAX + 1]; #endif - uv_err_t r = uv_cwd(buf, ARRAY_SIZE(buf) - 1); - if (r.code != UV_OK) { - return ThrowUVException(r.code, "uv_cwd"); + int err = uv_cwd(buf, ARRAY_SIZE(buf) - 1); + if (err) { + return ThrowUVException(err, "uv_cwd"); } buf[ARRAY_SIZE(buf) - 1] = '\0'; @@ -1698,7 +1661,7 @@ void Exit(const FunctionCallbackInfo& args) { static void Uptime(const FunctionCallbackInfo& args) { HandleScope scope(node_isolate); double uptime; - if (uv_uptime(&uptime).code != UV_OK) return; + if (uv_uptime(&uptime)) return; args.GetReturnValue().Set(uptime - prog_start_time); } @@ -1708,10 +1671,9 @@ void MemoryUsage(const FunctionCallbackInfo& args) { size_t rss; - uv_err_t err = uv_resident_set_memory(&rss); - - if (err.code != UV_OK) { - return ThrowUVException(err.code, "uv_resident_set_memory"); + int err = uv_resident_set_memory(&rss); + if (err) { + return ThrowUVException(err, "uv_resident_set_memory"); } Local info = Object::New(); @@ -1747,12 +1709,8 @@ void Kill(const FunctionCallbackInfo& args) { int pid = args[0]->IntegerValue(); int sig = args[1]->Int32Value(); - uv_err_t err = uv_kill(pid, sig); - - if (err.code != UV_OK) { - SetErrno(err); - args.GetReturnValue().Set(-1); - } + int err = uv_kill(pid, sig); + args.GetReturnValue().Set(err); } // used in Hrtime() below diff --git a/src/node.h b/src/node.h index 55c65a3b66..4fcdd604cb 100644 --- a/src/node.h +++ b/src/node.h @@ -239,8 +239,6 @@ node_module_struct* get_builtin_module(const char *name); */ NODE_EXTERN void AtExit(void (*cb)(void* arg), void* arg = 0); -NODE_EXTERN void SetErrno(uv_err_t err); - } // namespace node #endif // SRC_NODE_H_ diff --git a/src/node.js b/src/node.js index 061cbf9c3c..e9bcd0bcd8 100644 --- a/src/node.js +++ b/src/node.js @@ -626,23 +626,23 @@ }; process.kill = function(pid, sig) { - var r; + var err; // preserve null signal if (0 === sig) { - r = process._kill(pid, 0); + err = process._kill(pid, 0); } else { sig = sig || 'SIGTERM'; if (startup.lazyConstants()[sig]) { - r = process._kill(pid, startup.lazyConstants()[sig]); + err = process._kill(pid, startup.lazyConstants()[sig]); } else { throw new Error('Unknown signal: ' + sig); } } - if (r) { + if (err) { var errnoException = NativeModule.require('util')._errnoException; - throw errnoException(process._errno, 'kill'); + throw errnoException(err, 'kill'); } return true; @@ -673,11 +673,11 @@ wrap.onsignal = function() { process.emit(type); }; var signum = startup.lazyConstants()[type]; - var r = wrap.start(signum); - if (r) { + var err = wrap.start(signum); + if (err) { wrap.close(); var errnoException = NativeModule.require('util')._errnoException; - throw errnoException(process._errno, 'uv_signal_start'); + throw errnoException(err, 'uv_signal_start'); } signalWraps[type] = wrap; diff --git a/src/node_file.cc b/src/node_file.cc index df99794027..bc09678e42 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -104,17 +104,12 @@ static void After(uv_fs_t *req) { // (Feel free to increase this if you need more) Local argv[2]; - // NOTE: This may be needed to be changed if something returns a -1 - // for a success, which is possible. - if (req->result == -1) { + if (req->result < 0) { // If the request doesn't have a path parameter set. - - if (!req->path) { - argv[0] = UVException(req->errorno, - NULL, - req_wrap->syscall()); + if (req->path == NULL) { + argv[0] = UVException(req->result, NULL, req_wrap->syscall()); } else { - argv[0] = UVException(req->errorno, + argv[0] = UVException(req->result, NULL, req_wrap->syscall(), static_cast(req->path)); @@ -225,30 +220,29 @@ struct fs_req_wrap { #define ASYNC_CALL(func, callback, ...) \ FSReqWrap* req_wrap = new FSReqWrap(#func); \ - int r = uv_fs_##func(uv_default_loop(), &req_wrap->req_, \ + int err = uv_fs_ ## func(uv_default_loop(), &req_wrap->req_, \ __VA_ARGS__, After); \ req_wrap->object()->Set(oncomplete_sym, callback); \ req_wrap->Dispatched(); \ - if (r < 0) { \ + if (err < 0) { \ uv_fs_t* req = &req_wrap->req_; \ - req->result = r; \ + req->result = err; \ req->path = NULL; \ - req->errorno = uv_last_error(uv_default_loop()).code; \ After(req); \ } \ args.GetReturnValue().Set(req_wrap->persistent()); #define SYNC_CALL(func, path, ...) \ fs_req_wrap req_wrap; \ - int result = uv_fs_##func(uv_default_loop(), &req_wrap.req, __VA_ARGS__, NULL); \ - if (result < 0) { \ - int code = uv_last_error(uv_default_loop()).code; \ - return ThrowUVException(code, #func, "", path); \ - } + int err = uv_fs_ ## func(uv_default_loop(), \ + &req_wrap.req, \ + __VA_ARGS__, \ + NULL); \ + if (err < 0) return ThrowUVException(err, #func, NULL, path); \ #define SYNC_REQ req_wrap.req -#define SYNC_RESULT result +#define SYNC_RESULT err static void Close(const FunctionCallbackInfo& args) { diff --git a/src/node_os.cc b/src/node_os.cc index 6e11002be9..5b6e30b370 100644 --- a/src/node_os.cc +++ b/src/node_os.cc @@ -131,8 +131,8 @@ static void GetCPUInfo(const FunctionCallbackInfo& args) { uv_cpu_info_t* cpu_infos; int count, i; - uv_err_t err = uv_cpu_info(&cpu_infos, &count); - if (err.code != UV_OK) return; + int err = uv_cpu_info(&cpu_infos, &count); + if (err) return; Local cpus = Array::New(); for (i = 0; i < count; i++) { @@ -180,9 +180,8 @@ static void GetTotalMemory(const FunctionCallbackInfo& args) { static void GetUptime(const FunctionCallbackInfo& args) { HandleScope scope(node_isolate); double uptime; - uv_err_t err = uv_uptime(&uptime); - if (err.code != UV_OK) return; - args.GetReturnValue().Set(uptime); + int err = uv_uptime(&uptime); + if (err == 0) args.GetReturnValue().Set(uptime); } @@ -208,9 +207,9 @@ static void GetInterfaceAddresses(const FunctionCallbackInfo& args) { Local name, family; Local ifarr; - uv_err_t err = uv_interface_addresses(&interfaces, &count); - if (err.code != UV_OK) { - return ThrowUVException(err.code, "uv_interface_addresses"); + int err = uv_interface_addresses(&interfaces, &count); + if (err) { + return ThrowUVException(err, "uv_interface_addresses"); } ret = Object::New(); diff --git a/src/node_stat_watcher.cc b/src/node_stat_watcher.cc index 07ba5efce5..18dd34a0e3 100644 --- a/src/node_stat_watcher.cc +++ b/src/node_stat_watcher.cc @@ -86,9 +86,6 @@ void StatWatcher::Callback(uv_fs_poll_t* handle, argv[0] = BuildStatsObject(curr); argv[1] = BuildStatsObject(prev); argv[2] = Integer::New(status, node_isolate); - if (status == -1) { - SetErrno(uv_last_error(wrap->watcher_->loop)); - } if (onchange_sym.IsEmpty()) { onchange_sym = String::New("onchange"); } diff --git a/src/pipe_wrap.cc b/src/pipe_wrap.cc index 3943d34391..1544789490 100644 --- a/src/pipe_wrap.cc +++ b/src/pipe_wrap.cc @@ -41,6 +41,7 @@ using v8::Object; using v8::Persistent; using v8::PropertyAttribute; using v8::String; +using v8::Undefined; using v8::Value; static Persistent pipeConstructor; @@ -145,13 +146,8 @@ void PipeWrap::Bind(const FunctionCallbackInfo& args) { UNWRAP(PipeWrap) String::AsciiValue name(args[0]); - - int r = uv_pipe_bind(&wrap->handle_, *name); - - // Error starting the pipe. - if (r) SetErrno(uv_last_error(uv_default_loop())); - - args.GetReturnValue().Set(r); + int err = uv_pipe_bind(&wrap->handle_, *name); + args.GetReturnValue().Set(err); } @@ -174,15 +170,10 @@ void PipeWrap::Listen(const FunctionCallbackInfo& args) { UNWRAP(PipeWrap) int backlog = args[0]->Int32Value(); - - int r = uv_listen(reinterpret_cast(&wrap->handle_), - backlog, - OnConnection); - - // Error starting the pipe. - if (r) SetErrno(uv_last_error(uv_default_loop())); - - args.GetReturnValue().Set(r); + int err = uv_listen(reinterpret_cast(&wrap->handle_), + backlog, + OnConnection); + args.GetReturnValue().Set(err); } @@ -197,9 +188,13 @@ void PipeWrap::OnConnection(uv_stream_t* handle, int status) { // uv_close() on the handle. assert(wrap->persistent().IsEmpty() == false); + Local argv[] = { + Integer::New(status, node_isolate), + Undefined() + }; + if (status != 0) { - SetErrno(uv_last_error(uv_default_loop())); - MakeCallback(wrap->object(), "onconnection", 0, NULL); + MakeCallback(wrap->object(), "onconnection", ARRAY_SIZE(argv), argv); return; } @@ -215,7 +210,7 @@ void PipeWrap::OnConnection(uv_stream_t* handle, int status) { if (uv_accept(handle, client_handle)) return; // Successful accept. Call the onconnection callback in JavaScript land. - Local argv[1] = { client_obj }; + argv[1] = client_obj; if (onconnection_sym.IsEmpty()) { onconnection_sym = String::New("onconnection"); } @@ -236,7 +231,6 @@ void PipeWrap::AfterConnect(uv_connect_t* req, int status) { bool readable, writable; if (status) { - SetErrno(uv_last_error(uv_default_loop())); readable = writable = 0; } else { readable = uv_is_readable(req->handle) != 0; @@ -277,18 +271,20 @@ void PipeWrap::Connect(const FunctionCallbackInfo& args) { UNWRAP(PipeWrap) - String::AsciiValue name(args[0]); + assert(args[0]->IsObject()); + assert(args[1]->IsString()); - ConnectWrap* req_wrap = new ConnectWrap(); + Local req_wrap_obj = args[0].As(); + String::AsciiValue name(args[1]); + ConnectWrap* req_wrap = new ConnectWrap(req_wrap_obj); uv_pipe_connect(&req_wrap->req_, &wrap->handle_, *name, AfterConnect); - req_wrap->Dispatched(); - args.GetReturnValue().Set(req_wrap->persistent()); + args.GetReturnValue().Set(0); // uv_pipe_connect() doesn't return errors. } diff --git a/src/process_wrap.cc b/src/process_wrap.cc index dac6f2955e..5044c124e8 100644 --- a/src/process_wrap.cc +++ b/src/process_wrap.cc @@ -217,12 +217,9 @@ class ProcessWrap : public HandleWrap { options.flags |= UV_PROCESS_DETACHED; } - int r = uv_spawn(uv_default_loop(), &wrap->process_, options); + int err = uv_spawn(uv_default_loop(), &wrap->process_, options); - if (r) { - SetErrno(uv_last_error(uv_default_loop())); - } - else { + if (err == 0) { assert(wrap->process_.data == wrap); wrap->object()->Set(String::New("pid"), Integer::New(wrap->process_.pid, node_isolate)); @@ -240,7 +237,7 @@ class ProcessWrap : public HandleWrap { delete[] options.stdio; - args.GetReturnValue().Set(r); + args.GetReturnValue().Set(err); } static void Kill(const FunctionCallbackInfo& args) { @@ -248,9 +245,8 @@ class ProcessWrap : public HandleWrap { UNWRAP(ProcessWrap) int signal = args[0]->Int32Value(); - int r = uv_process_kill(&wrap->process_, signal); - if (r) SetErrno(uv_last_error(uv_default_loop())); - args.GetReturnValue().Set(r); + int err = uv_process_kill(&wrap->process_, signal); + args.GetReturnValue().Set(err); } static void OnExit(uv_process_t* handle, int exit_status, int term_signal) { @@ -260,15 +256,11 @@ class ProcessWrap : public HandleWrap { assert(wrap); assert(&wrap->process_ == handle); - Local argv[2] = { + Local argv[] = { Integer::New(exit_status, node_isolate), String::New(signo_string(term_signal)) }; - if (exit_status == -1) { - SetErrno(uv_last_error(uv_default_loop())); - } - if (onexit_sym.IsEmpty()) { onexit_sym = String::New("onexit"); } diff --git a/src/signal_wrap.cc b/src/signal_wrap.cc index 201e033592..2120a2f866 100644 --- a/src/signal_wrap.cc +++ b/src/signal_wrap.cc @@ -86,18 +86,16 @@ class SignalWrap : public HandleWrap { UNWRAP(SignalWrap) int signum = args[0]->Int32Value(); - int r = uv_signal_start(&wrap->handle_, OnSignal, signum); - if (r) SetErrno(uv_last_error(uv_default_loop())); - args.GetReturnValue().Set(r); + int err = uv_signal_start(&wrap->handle_, OnSignal, signum); + args.GetReturnValue().Set(err); } static void Stop(const FunctionCallbackInfo& args) { HandleScope scope(node_isolate); UNWRAP(SignalWrap) - int r = uv_signal_stop(&wrap->handle_); - if (r) SetErrno(uv_last_error(uv_default_loop())); - args.GetReturnValue().Set(r); + int err = uv_signal_stop(&wrap->handle_); + args.GetReturnValue().Set(err); } static void OnSignal(uv_signal_t* handle, int signum) { diff --git a/src/stream_wrap.cc b/src/stream_wrap.cc index 73d0a59495..e52dcf7d8b 100644 --- a/src/stream_wrap.cc +++ b/src/stream_wrap.cc @@ -45,6 +45,7 @@ using v8::Number; using v8::Object; using v8::PropertyCallbackInfo; using v8::String; +using v8::Undefined; using v8::Value; @@ -106,17 +107,14 @@ void StreamWrap::ReadStart(const FunctionCallbackInfo& args) { bool ipc_pipe = wrap->stream_->type == UV_NAMED_PIPE && reinterpret_cast(wrap->stream_)->ipc; - int r; + int err; if (ipc_pipe) { - r = uv_read2_start(wrap->stream_, OnAlloc, OnRead2); + err = uv_read2_start(wrap->stream_, OnAlloc, OnRead2); } else { - r = uv_read_start(wrap->stream_, OnAlloc, OnRead); + err = uv_read_start(wrap->stream_, OnAlloc, OnRead); } - // Error starting the tcp. - if (r) SetErrno(uv_last_error(uv_default_loop())); - - args.GetReturnValue().Set(r); + args.GetReturnValue().Set(err); } @@ -125,12 +123,8 @@ void StreamWrap::ReadStop(const FunctionCallbackInfo& args) { UNWRAP(StreamWrap) - int r = uv_read_stop(wrap->stream_); - - // Error starting the tcp. - if (r) SetErrno(uv_last_error(uv_default_loop())); - - args.GetReturnValue().Set(r); + int err = uv_read_stop(wrap->stream_); + args.GetReturnValue().Set(err); } @@ -215,48 +209,50 @@ void StreamWrap::WriteBuffer(const FunctionCallbackInfo& args) { UNWRAP(StreamWrap) - // The first argument is a buffer. - assert(args.Length() >= 1 && Buffer::HasInstance(args[0])); - size_t length = Buffer::Length(args[0]); + assert(args[0]->IsObject()); + assert(Buffer::HasInstance(args[1])); + + Local req_wrap_obj = args[0].As(); + Local buf_obj = args[1].As(); + + size_t length = Buffer::Length(buf_obj); char* storage = new char[sizeof(WriteWrap)]; - WriteWrap* req_wrap = new (storage) WriteWrap(wrap); + WriteWrap* req_wrap = new (storage) WriteWrap(req_wrap_obj, wrap); - Local req_wrap_obj = req_wrap->object(); - req_wrap_obj->SetHiddenValue(buffer_sym, args[0]); + req_wrap_obj->SetHiddenValue(buffer_sym, buf_obj); uv_buf_t buf; - WriteBuffer(args[0], &buf); - - int r = wrap->callbacks_->DoWrite(req_wrap, - &buf, - 1, - NULL, - StreamWrap::AfterWrite); + WriteBuffer(buf_obj, &buf); + int err = wrap->callbacks_->DoWrite(req_wrap, + &buf, + 1, + NULL, + StreamWrap::AfterWrite); req_wrap->Dispatched(); req_wrap_obj->Set(bytes_sym, Integer::NewFromUnsigned(length, node_isolate)); - if (r) { - SetErrno(uv_last_error(uv_default_loop())); + if (err) { req_wrap->~WriteWrap(); delete[] storage; - } else { - args.GetReturnValue().Set(req_wrap->persistent()); } + + args.GetReturnValue().Set(err); } template void StreamWrap::WriteStringImpl(const FunctionCallbackInfo& args) { HandleScope scope(node_isolate); - int r; + int err; UNWRAP(StreamWrap) - if (args.Length() < 1) - return ThrowTypeError("Not enough arguments"); + assert(args[0]->IsObject()); + assert(args[1]->IsString()); - Local string = args[0]->ToString(); + Local req_wrap_obj = args[0].As(); + Local string = args[1].As(); // Compute the size of the storage that the string will be flattened into. // For UTF8 strings that are very long, go ahead and take the hit for @@ -268,14 +264,12 @@ void StreamWrap::WriteStringImpl(const FunctionCallbackInfo& args) { storage_size = StringBytes::StorageSize(string, encoding); if (storage_size > INT_MAX) { - uv_err_t err; - err.code = UV_ENOBUFS; - SetErrno(err); + args.GetReturnValue().Set(UV_ENOBUFS); return; } char* storage = new char[sizeof(WriteWrap) + storage_size + 15]; - WriteWrap* req_wrap = new (storage) WriteWrap(wrap); + WriteWrap* req_wrap = new (storage) WriteWrap(req_wrap_obj, wrap); char* data = reinterpret_cast(ROUND_UP( reinterpret_cast(storage) + sizeof(WriteWrap), 16)); @@ -294,16 +288,16 @@ void StreamWrap::WriteStringImpl(const FunctionCallbackInfo& args) { reinterpret_cast(wrap->stream_)->ipc; if (!ipc_pipe) { - r = wrap->callbacks_->DoWrite(req_wrap, - &buf, - 1, - NULL, - StreamWrap::AfterWrite); + err = wrap->callbacks_->DoWrite(req_wrap, + &buf, + 1, + NULL, + StreamWrap::AfterWrite); } else { uv_handle_t* send_handle = NULL; - if (args[1]->IsObject()) { - Local send_handle_obj = args[1]->ToObject(); + if (args[2]->IsObject()) { + Local send_handle_obj = args[2]->ToObject(); assert(send_handle_obj->InternalFieldCount() > 0); HandleWrap* send_handle_wrap = static_cast( send_handle_obj->GetAlignedPointerFromInternalField(0)); @@ -318,23 +312,22 @@ void StreamWrap::WriteStringImpl(const FunctionCallbackInfo& args) { req_wrap->object()->Set(handle_sym, send_handle_obj); } - r = wrap->callbacks_->DoWrite(req_wrap, - &buf, - 1, - reinterpret_cast(send_handle), - StreamWrap::AfterWrite); + err = wrap->callbacks_->DoWrite(req_wrap, + &buf, + 1, + reinterpret_cast(send_handle), + StreamWrap::AfterWrite); } req_wrap->Dispatched(); req_wrap->object()->Set(bytes_sym, Number::New(node_isolate, data_size)); - if (r) { - SetErrno(uv_last_error(uv_default_loop())); + if (err) { req_wrap->~WriteWrap(); delete[] storage; - } else { - args.GetReturnValue().Set(req_wrap->persistent()); } + + args.GetReturnValue().Set(err); } @@ -343,13 +336,11 @@ void StreamWrap::Writev(const FunctionCallbackInfo& args) { UNWRAP(StreamWrap) - if (args.Length() < 1) - return ThrowTypeError("Not enough arguments"); - - if (!args[0]->IsArray()) - return ThrowTypeError("Argument should be array"); + assert(args[0]->IsObject()); + assert(args[1]->IsArray()); - Handle chunks = args[0].As(); + Local req_wrap_obj = args[0].As(); + Local chunks = args[1].As(); size_t count = chunks->Length() >> 1; uv_buf_t bufs_[16]; @@ -377,9 +368,7 @@ void StreamWrap::Writev(const FunctionCallbackInfo& args) { } if (storage_size > INT_MAX) { - uv_err_t err; - err.code = UV_ENOBUFS; - SetErrno(err); + args.GetReturnValue().Set(UV_ENOBUFS); return; } @@ -388,7 +377,7 @@ void StreamWrap::Writev(const FunctionCallbackInfo& args) { storage_size += sizeof(WriteWrap); char* storage = new char[storage_size]; - WriteWrap* req_wrap = new (storage) WriteWrap(wrap); + WriteWrap* req_wrap = new (storage) WriteWrap(req_wrap_obj, wrap); uint32_t bytes = 0; size_t offset = sizeof(WriteWrap); @@ -418,11 +407,11 @@ void StreamWrap::Writev(const FunctionCallbackInfo& args) { bytes += str_size; } - int r = wrap->callbacks_->DoWrite(req_wrap, - bufs, - count, - NULL, - StreamWrap::AfterWrite); + int err = wrap->callbacks_->DoWrite(req_wrap, + bufs, + count, + NULL, + StreamWrap::AfterWrite); // Deallocate space if (bufs != bufs_) @@ -431,13 +420,12 @@ void StreamWrap::Writev(const FunctionCallbackInfo& args) { req_wrap->Dispatched(); req_wrap->object()->Set(bytes_sym, Number::New(node_isolate, bytes)); - if (r) { - SetErrno(uv_last_error(uv_default_loop())); + if (err) { req_wrap->~WriteWrap(); delete[] storage; - } else { - args.GetReturnValue().Set(req_wrap->persistent()); } + + args.GetReturnValue().Set(err); } @@ -472,10 +460,6 @@ void StreamWrap::AfterWrite(uv_write_t* req, int status) { req_wrap_obj->Delete(handle_sym); } - if (status) { - SetErrno(uv_last_error(uv_default_loop())); - } - wrap->callbacks_->AfterWrite(req_wrap); Local argv[] = { @@ -496,24 +480,20 @@ void StreamWrap::Shutdown(const FunctionCallbackInfo& args) { UNWRAP(StreamWrap) - ShutdownWrap* req_wrap = new ShutdownWrap(); - - int r = wrap->callbacks_->DoShutdown(req_wrap, AfterShutdown); + assert(args[0]->IsObject()); + Local req_wrap_obj = args[0].As(); + ShutdownWrap* req_wrap = new ShutdownWrap(req_wrap_obj); + int err = wrap->callbacks_->DoShutdown(req_wrap, AfterShutdown); req_wrap->Dispatched(); - - if (r) { - SetErrno(uv_last_error(uv_default_loop())); - delete req_wrap; - } else { - args.GetReturnValue().Set(req_wrap->persistent()); - } + if (err) delete req_wrap; + args.GetReturnValue().Set(err); } void StreamWrap::AfterShutdown(uv_shutdown_t* req, int status) { - ReqWrap* req_wrap = (ReqWrap*) req->data; - StreamWrap* wrap = (StreamWrap*) req->handle->data; + ShutdownWrap* req_wrap = static_cast(req->data); + StreamWrap* wrap = static_cast(req->handle->data); // The wrap and request objects should still be there. assert(req_wrap->persistent().IsEmpty() == false); @@ -521,10 +501,6 @@ void StreamWrap::AfterShutdown(uv_shutdown_t* req, int status) { HandleScope scope(node_isolate); - if (status) { - SetErrno(uv_last_error(uv_default_loop())); - } - Local req_wrap_obj = req_wrap->object(); Local argv[3] = { Integer::New(status, node_isolate), @@ -589,11 +565,16 @@ void StreamWrapCallbacks::DoRead(uv_stream_t* handle, uv_handle_type pending) { HandleScope scope(node_isolate); + Local argv[] = { + Integer::New(nread, node_isolate), + Undefined(), + Undefined() + }; + if (nread < 0) { if (buf.base != NULL) free(buf.base); - SetErrno(uv_last_error(uv_default_loop())); - MakeCallback(Self(), onread_sym, 0, NULL); + MakeCallback(Self(), onread_sym, ARRAY_SIZE(argv), argv); return; } @@ -604,13 +585,8 @@ void StreamWrapCallbacks::DoRead(uv_stream_t* handle, } buf.base = static_cast(realloc(buf.base, nread)); - assert(static_cast(nread) <= buf.len); - - int argc = 1; - Local argv[2] = { - Buffer::Use(buf.base, nread) - }; + argv[1] = Buffer::Use(buf.base, nread); Local pending_obj; if (pending == UV_TCP) { @@ -624,11 +600,10 @@ void StreamWrapCallbacks::DoRead(uv_stream_t* handle, } if (!pending_obj.IsEmpty()) { - argv[1] = pending_obj; - argc++; + argv[2] = pending_obj; } - MakeCallback(wrap_->object(), onread_sym, argc, argv); + MakeCallback(wrap_->object(), onread_sym, ARRAY_SIZE(argv), argv); } diff --git a/src/stream_wrap.h b/src/stream_wrap.h index 6ef20d364b..0a431c1486 100644 --- a/src/stream_wrap.h +++ b/src/stream_wrap.h @@ -37,7 +37,8 @@ typedef class ReqWrap ShutdownWrap; class WriteWrap: public ReqWrap { public: - explicit WriteWrap(StreamWrap* wrap) { + explicit WriteWrap(v8::Local obj, StreamWrap* wrap) + : ReqWrap(obj) { wrap_ = wrap; } diff --git a/src/tcp_wrap.cc b/src/tcp_wrap.cc index 7401dd07ea..9be4121063 100644 --- a/src/tcp_wrap.cc +++ b/src/tcp_wrap.cc @@ -39,11 +39,11 @@ using v8::Handle; using v8::HandleScope; using v8::Integer; using v8::Local; -using v8::Null; using v8::Object; using v8::Persistent; using v8::PropertyAttribute; using v8::String; +using v8::Undefined; using v8::Value; static Persistent tcpConstructor; @@ -168,14 +168,19 @@ void TCPWrap::GetSockName(const FunctionCallbackInfo& args) { UNWRAP(TCPWrap) + assert(args[0]->IsObject()); + Local out = args[0].As(); + int addrlen = sizeof(address); - int r = uv_tcp_getsockname(&wrap->handle_, - reinterpret_cast(&address), - &addrlen); - if (r) return SetErrno(uv_last_error(uv_default_loop())); + int err = uv_tcp_getsockname(&wrap->handle_, + reinterpret_cast(&address), + &addrlen); + if (err == 0) { + const sockaddr* addr = reinterpret_cast(&address); + AddressToJS(addr, out); + } - const sockaddr* addr = reinterpret_cast(&address); - args.GetReturnValue().Set(AddressToJS(addr)); + args.GetReturnValue().Set(err); } @@ -185,14 +190,19 @@ void TCPWrap::GetPeerName(const FunctionCallbackInfo& args) { UNWRAP(TCPWrap) + assert(args[0]->IsObject()); + Local out = args[0].As(); + int addrlen = sizeof(address); - int r = uv_tcp_getpeername(&wrap->handle_, - reinterpret_cast(&address), - &addrlen); - if (r) return SetErrno(uv_last_error(uv_default_loop())); + int err = uv_tcp_getpeername(&wrap->handle_, + reinterpret_cast(&address), + &addrlen); + if (err == 0) { + const sockaddr* addr = reinterpret_cast(&address); + AddressToJS(addr, out); + } - const sockaddr* addr = reinterpret_cast(&address); - args.GetReturnValue().Set(AddressToJS(addr)); + args.GetReturnValue().Set(err); } @@ -202,8 +212,8 @@ void TCPWrap::SetNoDelay(const FunctionCallbackInfo& args) { UNWRAP(TCPWrap) int enable = static_cast(args[0]->BooleanValue()); - int r = uv_tcp_nodelay(&wrap->handle_, enable); - if (r) SetErrno(uv_last_error(uv_default_loop())); + int err = uv_tcp_nodelay(&wrap->handle_, enable); + args.GetReturnValue().Set(err); } @@ -215,8 +225,8 @@ void TCPWrap::SetKeepAlive(const FunctionCallbackInfo& args) { int enable = args[0]->Int32Value(); unsigned int delay = args[1]->Uint32Value(); - int r = uv_tcp_keepalive(&wrap->handle_, enable, delay); - if (r) SetErrno(uv_last_error(uv_default_loop())); + int err = uv_tcp_keepalive(&wrap->handle_, enable, delay); + args.GetReturnValue().Set(err); } @@ -227,8 +237,8 @@ void TCPWrap::SetSimultaneousAccepts(const FunctionCallbackInfo& args) { UNWRAP(TCPWrap) bool enable = args[0]->BooleanValue(); - int r = uv_tcp_simultaneous_accepts(&wrap->handle_, enable ? 1 : 0); - if (r) SetErrno(uv_last_error(uv_default_loop())); + int err = uv_tcp_simultaneous_accepts(&wrap->handle_, enable); + args.GetReturnValue().Set(err); } #endif @@ -250,12 +260,9 @@ void TCPWrap::Bind(const FunctionCallbackInfo& args) { int port = args[1]->Int32Value(); struct sockaddr_in address = uv_ip4_addr(*ip_address, port); - int r = uv_tcp_bind(&wrap->handle_, address); - - // Error starting the tcp. - if (r) SetErrno(uv_last_error(uv_default_loop())); + int err = uv_tcp_bind(&wrap->handle_, address); - args.GetReturnValue().Set(r); + args.GetReturnValue().Set(err); } @@ -268,12 +275,9 @@ void TCPWrap::Bind6(const FunctionCallbackInfo& args) { int port = args[1]->Int32Value(); struct sockaddr_in6 address = uv_ip6_addr(*ip6_address, port); - int r = uv_tcp_bind6(&wrap->handle_, address); - - // Error starting the tcp. - if (r) SetErrno(uv_last_error(uv_default_loop())); + int err = uv_tcp_bind6(&wrap->handle_, address); - args.GetReturnValue().Set(r); + args.GetReturnValue().Set(err); } @@ -283,15 +287,10 @@ void TCPWrap::Listen(const FunctionCallbackInfo& args) { UNWRAP(TCPWrap) int backlog = args[0]->Int32Value(); - - int r = uv_listen(reinterpret_cast(&wrap->handle_), - backlog, - OnConnection); - - // Error starting the tcp. - if (r) SetErrno(uv_last_error(uv_default_loop())); - - args.GetReturnValue().Set(r); + int err = uv_listen(reinterpret_cast(&wrap->handle_), + backlog, + OnConnection); + args.GetReturnValue().Set(err); } @@ -305,7 +304,10 @@ void TCPWrap::OnConnection(uv_stream_t* handle, int status) { // uv_close() on the handle. assert(wrap->persistent().IsEmpty() == false); - Local argv[1]; + Local argv[2] = { + Integer::New(status, node_isolate), + Undefined() + }; if (status == 0) { // Instantiate the client javascript object and handle. @@ -321,10 +323,7 @@ void TCPWrap::OnConnection(uv_stream_t* handle, int status) { if (uv_accept(handle, client_handle)) return; // Successful accept. Call the onconnection callback in JavaScript land. - argv[0] = client_obj; - } else { - SetErrno(uv_last_error(uv_default_loop())); - argv[0] = Null(node_isolate); + argv[1] = client_obj; } MakeCallback(wrap->object(), onconnection_sym, ARRAY_SIZE(argv), argv); @@ -341,10 +340,6 @@ void TCPWrap::AfterConnect(uv_connect_t* req, int status) { assert(req_wrap->persistent().IsEmpty() == false); assert(wrap->persistent().IsEmpty() == false); - if (status) { - SetErrno(uv_last_error(uv_default_loop())); - } - Local req_wrap_obj = req_wrap->object(); Local argv[5] = { Integer::New(status, node_isolate), @@ -364,27 +359,29 @@ void TCPWrap::Connect(const FunctionCallbackInfo& args) { UNWRAP(TCPWrap) - String::AsciiValue ip_address(args[0]); - int port = args[1]->Int32Value(); + assert(args[0]->IsObject()); + assert(args[1]->IsString()); + assert(args[2]->Uint32Value()); + + Local req_wrap_obj = args[0].As(); + String::AsciiValue ip_address(args[1]); + int port = args[2]->Uint32Value(); struct sockaddr_in address = uv_ip4_addr(*ip_address, port); // I hate when people program C++ like it was C, and yet I do it too. // I'm too lazy to come up with the perfect class hierarchy here. Let's // just do some type munging. - ConnectWrap* req_wrap = new ConnectWrap(); - - int r = uv_tcp_connect(&req_wrap->req_, &wrap->handle_, address, - AfterConnect); + ConnectWrap* req_wrap = new ConnectWrap(req_wrap_obj); + int err = uv_tcp_connect(&req_wrap->req_, + &wrap->handle_, + address, + AfterConnect); req_wrap->Dispatched(); + if (err) delete req_wrap; - if (r) { - SetErrno(uv_last_error(uv_default_loop())); - delete req_wrap; - } else { - args.GetReturnValue().Set(req_wrap->persistent()); - } + args.GetReturnValue().Set(err); } @@ -393,24 +390,26 @@ void TCPWrap::Connect6(const FunctionCallbackInfo& args) { UNWRAP(TCPWrap) - String::AsciiValue ip_address(args[0]); - int port = args[1]->Int32Value(); + assert(args[0]->IsObject()); + assert(args[1]->IsString()); + assert(args[2]->Uint32Value()); - struct sockaddr_in6 address = uv_ip6_addr(*ip_address, port); + Local req_wrap_obj = args[0].As(); + String::AsciiValue ip_address(args[1]); + int port = args[2]->Int32Value(); - ConnectWrap* req_wrap = new ConnectWrap(); + struct sockaddr_in6 address = uv_ip6_addr(*ip_address, port); - int r = uv_tcp_connect6(&req_wrap->req_, &wrap->handle_, address, - AfterConnect); + ConnectWrap* req_wrap = new ConnectWrap(req_wrap_obj); + int err = uv_tcp_connect6(&req_wrap->req_, + &wrap->handle_, + address, + AfterConnect); req_wrap->Dispatched(); + if (err) delete req_wrap; - if (r) { - SetErrno(uv_last_error(uv_default_loop())); - delete req_wrap; - } else { - args.GetReturnValue().Set(req_wrap->persistent()); - } + args.GetReturnValue().Set(err); } diff --git a/src/timer_wrap.cc b/src/timer_wrap.cc index 40bc3edd49..1a3d43cc05 100644 --- a/src/timer_wrap.cc +++ b/src/timer_wrap.cc @@ -90,27 +90,24 @@ class TimerWrap : public HandleWrap { int64_t timeout = args[0]->IntegerValue(); int64_t repeat = args[1]->IntegerValue(); - int r = uv_timer_start(&wrap->handle_, OnTimeout, timeout, repeat); - if (r) SetErrno(uv_last_error(uv_default_loop())); - args.GetReturnValue().Set(r); + int err = uv_timer_start(&wrap->handle_, OnTimeout, timeout, repeat); + args.GetReturnValue().Set(err); } static void Stop(const FunctionCallbackInfo& args) { HandleScope scope(node_isolate); UNWRAP(TimerWrap) - int r = uv_timer_stop(&wrap->handle_); - if (r) SetErrno(uv_last_error(uv_default_loop())); - args.GetReturnValue().Set(r); + int err = uv_timer_stop(&wrap->handle_); + args.GetReturnValue().Set(err); } static void Again(const FunctionCallbackInfo& args) { HandleScope scope(node_isolate); UNWRAP(TimerWrap) - int r = uv_timer_again(&wrap->handle_); - if (r) SetErrno(uv_last_error(uv_default_loop())); - args.GetReturnValue().Set(r); + int err = uv_timer_again(&wrap->handle_); + args.GetReturnValue().Set(err); } static void SetRepeat(const FunctionCallbackInfo& args) { @@ -127,7 +124,6 @@ class TimerWrap : public HandleWrap { UNWRAP(TimerWrap) int64_t repeat = uv_timer_get_repeat(&wrap->handle_); - if (repeat < 0) SetErrno(uv_last_error(uv_default_loop())); args.GetReturnValue().Set(static_cast(repeat)); } diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc index db93a98977..c014137f57 100644 --- a/src/tls_wrap.cc +++ b/src/tls_wrap.cc @@ -418,7 +418,6 @@ void TLSCallbacks::EncOutCb(uv_write_t* req, int status) { return; // Notify about error - SetErrno(uv_last_error(uv_default_loop())); Local arg = String::Concat( String::New("write cb error, status: "), Integer::New(status, node_isolate)->ToString()); @@ -483,8 +482,11 @@ void TLSCallbacks::ClearOut() { do { read = SSL_read(ssl_, out, sizeof(out)); if (read > 0) { - Handle buf = Buffer::New(out, read); - MakeCallback(Self(), onread_sym, 1, &buf); + Local argv[] = { + Integer::New(read, node_isolate), + Buffer::New(out, read) + }; + MakeCallback(Self(), onread_sym, ARRAY_SIZE(argv), argv); } } while (read > 0); @@ -621,12 +623,10 @@ void TLSCallbacks::DoRead(uv_stream_t* handle, uv_buf_t buf, uv_handle_type pending) { if (nread < 0) { - uv_err_t err = uv_last_error(uv_default_loop()); - SetErrno(err); - // Error should be emitted only after all data was read ClearOut(); - MakeCallback(Self(), onread_sym, 0, NULL); + Local arg = Integer::New(nread, node_isolate); + MakeCallback(Self(), onread_sym, 1, &arg); return; } diff --git a/src/tty_wrap.cc b/src/tty_wrap.cc index 457a3e8783..df34e56b13 100644 --- a/src/tty_wrap.cc +++ b/src/tty_wrap.cc @@ -29,6 +29,7 @@ namespace node { +using v8::Array; using v8::Function; using v8::FunctionCallbackInfo; using v8::FunctionTemplate; @@ -131,15 +132,18 @@ void TTYWrap::GetWindowSize(const FunctionCallbackInfo& args) { HandleScope scope(node_isolate); UNWRAP(TTYWrap) + assert(args[0]->IsArray()); int width, height; - int r = uv_tty_get_winsize(&wrap->handle_, &width, &height); - if (r) return SetErrno(uv_last_error(uv_default_loop())); + int err = uv_tty_get_winsize(&wrap->handle_, &width, &height); - Local a = v8::Array::New(2); - a->Set(0, Integer::New(width, node_isolate)); - a->Set(1, Integer::New(height, node_isolate)); - args.GetReturnValue().Set(a); + if (err == 0) { + Local a = args[0].As(); + a->Set(0, Integer::New(width, node_isolate)); + a->Set(1, Integer::New(height, node_isolate)); + } + + args.GetReturnValue().Set(err); } @@ -148,9 +152,8 @@ void TTYWrap::SetRawMode(const FunctionCallbackInfo& args) { UNWRAP(TTYWrap) - int r = uv_tty_set_mode(&wrap->handle_, args[0]->IsTrue()); - if (r) SetErrno(uv_last_error(uv_default_loop())); - args.GetReturnValue().Set(r); + int err = uv_tty_set_mode(&wrap->handle_, args[0]->IsTrue()); + args.GetReturnValue().Set(err); } diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc index bd6ac68e80..27799ffe9f 100644 --- a/src/udp_wrap.cc +++ b/src/udp_wrap.cc @@ -43,6 +43,7 @@ using v8::PropertyAttribute; using v8::PropertyCallbackInfo; using v8::String; using v8::Uint32; +using v8::Undefined; using v8::Value; typedef ReqWrap SendWrap; @@ -128,7 +129,7 @@ void UDPWrap::GetFD(Local, const PropertyCallbackInfo& args) { void UDPWrap::DoBind(const FunctionCallbackInfo& args, int family) { HandleScope scope(node_isolate); - int r; + int err; UNWRAP(UDPWrap) @@ -141,18 +142,17 @@ void UDPWrap::DoBind(const FunctionCallbackInfo& args, int family) { switch (family) { case AF_INET: - r = uv_udp_bind(&wrap->handle_, uv_ip4_addr(*address, port), flags); + err = uv_udp_bind(&wrap->handle_, uv_ip4_addr(*address, port), flags); break; case AF_INET6: - r = uv_udp_bind6(&wrap->handle_, uv_ip6_addr(*address, port), flags); + err = uv_udp_bind6(&wrap->handle_, uv_ip6_addr(*address, port), flags); break; default: assert(0 && "unexpected address family"); abort(); } - if (r) SetErrno(uv_last_error(uv_default_loop())); - args.GetReturnValue().Set(r); + args.GetReturnValue().Set(err); } @@ -172,9 +172,8 @@ void UDPWrap::Bind6(const FunctionCallbackInfo& args) { UNWRAP(UDPWrap) \ assert(args.Length() == 1); \ int flag = args[0]->Int32Value(); \ - int r = fn(&wrap->handle_, flag); \ - if (r) SetErrno(uv_last_error(uv_default_loop())); \ - args.GetReturnValue().Set(r); \ + int err = fn(&wrap->handle_, flag); \ + args.GetReturnValue().Set(err); \ } X(SetTTL, uv_udp_set_ttl) @@ -200,12 +199,11 @@ void UDPWrap::SetMembership(const FunctionCallbackInfo& args, iface_cstr = NULL; } - int r = uv_udp_set_membership(&wrap->handle_, - *address, - iface_cstr, - membership); - if (r) SetErrno(uv_last_error(uv_default_loop())); - args.GetReturnValue().Set(r); + int err = uv_udp_set_membership(&wrap->handle_, + *address, + iface_cstr, + membership); + args.GetReturnValue().Set(err); } @@ -221,38 +219,50 @@ void UDPWrap::DropMembership(const FunctionCallbackInfo& args) { void UDPWrap::DoSend(const FunctionCallbackInfo& args, int family) { HandleScope scope(node_isolate); - int r; - - // send(buffer, offset, length, port, address) - assert(args.Length() == 5); + int err; UNWRAP(UDPWrap) - assert(Buffer::HasInstance(args[0])); - Local buffer_obj = args[0]->ToObject(); + // send(req, buffer, offset, length, port, address) + assert(args[0]->IsObject()); + assert(Buffer::HasInstance(args[1])); + assert(args[2]->IsUint32()); + assert(args[3]->IsUint32()); + assert(args[4]->IsUint32()); + assert(args[5]->IsString()); + + Local req_wrap_obj = args[0].As(); + Local buffer_obj = args[1].As(); + size_t offset = args[2]->Uint32Value(); + size_t length = args[3]->Uint32Value(); + const unsigned short port = args[4]->Uint32Value(); + String::Utf8Value address(args[5]); - size_t offset = args[1]->Uint32Value(); - size_t length = args[2]->Uint32Value(); assert(offset < Buffer::Length(buffer_obj)); assert(length <= Buffer::Length(buffer_obj) - offset); - SendWrap* req_wrap = new SendWrap(); + SendWrap* req_wrap = new SendWrap(req_wrap_obj); req_wrap->object()->SetHiddenValue(buffer_sym, buffer_obj); uv_buf_t buf = uv_buf_init(Buffer::Data(buffer_obj) + offset, length); - const unsigned short port = args[3]->Uint32Value(); - String::Utf8Value address(args[4]); - switch (family) { case AF_INET: - r = uv_udp_send(&req_wrap->req_, &wrap->handle_, &buf, 1, - uv_ip4_addr(*address, port), OnSend); + err = uv_udp_send(&req_wrap->req_, + &wrap->handle_, + &buf, + 1, + uv_ip4_addr(*address, port), + OnSend); break; case AF_INET6: - r = uv_udp_send6(&req_wrap->req_, &wrap->handle_, &buf, 1, - uv_ip6_addr(*address, port), OnSend); + err = uv_udp_send6(&req_wrap->req_, + &wrap->handle_, + &buf, + 1, + uv_ip6_addr(*address, port), + OnSend); break; default: assert(0 && "unexpected address family"); @@ -260,14 +270,9 @@ void UDPWrap::DoSend(const FunctionCallbackInfo& args, int family) { } req_wrap->Dispatched(); + if (err) delete req_wrap; - if (r) { - SetErrno(uv_last_error(uv_default_loop())); - delete req_wrap; - } - else { - args.GetReturnValue().Set(req_wrap->persistent()); - } + args.GetReturnValue().Set(err); } @@ -285,11 +290,10 @@ void UDPWrap::RecvStart(const FunctionCallbackInfo& args) { HandleScope scope(node_isolate); UNWRAP(UDPWrap) + int err = uv_udp_recv_start(&wrap->handle_, OnAlloc, OnRecv); // UV_EALREADY means that the socket is already bound but that's okay - int r = uv_udp_recv_start(&wrap->handle_, OnAlloc, OnRecv); - bool ok = r == 0 || uv_last_error(uv_default_loop()).code == UV_EALREADY; - if (ok == false) SetErrno(uv_last_error(uv_default_loop())); - args.GetReturnValue().Set(ok); + if (err == UV_EALREADY) err = 0; + args.GetReturnValue().Set(err); } @@ -307,14 +311,20 @@ void UDPWrap::GetSockName(const FunctionCallbackInfo& args) { struct sockaddr_storage address; UNWRAP(UDPWrap) + assert(args[0]->IsObject()); + Local obj = args[0].As(); + int addrlen = sizeof(address); - int r = uv_udp_getsockname(&wrap->handle_, - reinterpret_cast(&address), - &addrlen); - if (r) return SetErrno(uv_last_error(uv_default_loop())); + int err = uv_udp_getsockname(&wrap->handle_, + reinterpret_cast(&address), + &addrlen); + + if (err == 0) { + const sockaddr* addr = reinterpret_cast(&address); + AddressToJS(addr, obj); + } - const sockaddr* addr = reinterpret_cast(&address); - args.GetReturnValue().Set(AddressToJS(addr)); + args.GetReturnValue().Set(err); } @@ -330,12 +340,8 @@ void UDPWrap::OnSend(uv_udp_send_t* req, int status) { assert(req_wrap->persistent().IsEmpty() == false); assert(wrap->persistent().IsEmpty() == false); - if (status) { - SetErrno(uv_last_error(uv_default_loop())); - } - Local req_wrap_obj = req_wrap->object(); - Local argv[4] = { + Local argv[] = { Integer::New(status, node_isolate), wrap->object(), req_wrap_obj, @@ -362,34 +368,34 @@ void UDPWrap::OnRecv(uv_udp_t* handle, uv_buf_t buf, struct sockaddr* addr, unsigned flags) { - HandleScope scope(node_isolate); - - UDPWrap* wrap = reinterpret_cast(handle->data); - - if (nread < 0) { + if (nread == 0) { if (buf.base != NULL) free(buf.base); - Local wrap_obj = wrap->object(); - Local argv[] = { wrap_obj }; - SetErrno(uv_last_error(uv_default_loop())); - MakeCallback(wrap_obj, onmessage_sym, ARRAY_SIZE(argv), argv); return; } - if (nread == 0) { + UDPWrap* wrap = reinterpret_cast(handle->data); + + HandleScope scope(node_isolate); + Local wrap_obj = wrap->object(); + Local argv[] = { + Integer::New(nread, node_isolate), + wrap_obj, + Undefined(), + Undefined() + }; + + if (nread < 0) { if (buf.base != NULL) free(buf.base); + MakeCallback(wrap_obj, onmessage_sym, ARRAY_SIZE(argv), argv); return; } buf.base = static_cast(realloc(buf.base, nread)); - Local wrap_obj = wrap->object(); - Local argv[] = { - wrap_obj, - Buffer::Use(buf.base, nread), - AddressToJS(addr) - }; + argv[2] = Buffer::Use(buf.base, nread); + argv[3] = AddressToJS(addr); MakeCallback(wrap_obj, onmessage_sym, ARRAY_SIZE(argv), argv); }