From 358d878655d410d8125b950684829041701c8554 Mon Sep 17 00:00:00 2001 From: Evan Lucas Date: Mon, 10 Mar 2014 15:42:58 -0500 Subject: [PATCH] net: give better error messages Add address and/or port to errors where applicable for better reporting. See #7005 Use util.format instead of string concatenation Also move some logic into util._errnoException. Passing an object as the fourth parameter to util._errnoException will now extend the returned error. --- lib/net.js | 61 ++++++++++++++++--- lib/util.js | 4 +- ...t-net-better-error-messages-listen-path.js | 39 ++++++++++++ .../test-net-better-error-messages-listen.js | 41 +++++++++++++ .../test-net-better-error-messages-path.js | 45 ++++++++++++++ ...net-better-error-messages-port-hostname.js | 46 ++++++++++++++ .../test-net-better-error-messages-port.js | 46 ++++++++++++++ 7 files changed, 273 insertions(+), 9 deletions(-) create mode 100644 test/simple/test-net-better-error-messages-listen-path.js create mode 100644 test/simple/test-net-better-error-messages-listen.js create mode 100644 test/simple/test-net-better-error-messages-path.js create mode 100644 test/simple/test-net-better-error-messages-port-hostname.js create mode 100644 test/simple/test-net-better-error-messages-port.js diff --git a/lib/net.js b/lib/net.js index a267cefe9676..040a9c725a07 100644 --- a/lib/net.js +++ b/lib/net.js @@ -739,7 +739,12 @@ function afterWrite(status, handle, req, err) { } if (status < 0) { - var ex = errnoException(status, 'write', err); + err = util.format('%s %s:%s', err || '', req.address, req.port); + var additions = { + address: req.address + }; + if (req.port) additions.port = req.port; + var ex = errnoException(status, 'write', err, additions); debug('write failure', ex); self._destroy(ex, req.cb); return; @@ -801,7 +806,13 @@ function connect(self, address, port, addressType, localAddress, localPort) { err = bind(localAddress, localPort); if (err) { - self._destroy(errnoException(err, 'bind')); + var details = util.format('%s:%s', address, port || ''); + var additions = { + address: address + }; + if (port) additions.port = port; + var ex = errnoException(err, 'bind', details, additions); + self._destroy(ex); return; } } @@ -812,17 +823,26 @@ function connect(self, address, port, addressType, localAddress, localPort) { if (port <= 0 || port > 65535) throw new RangeError('Port should be > 0 and < 65536'); + req.port = port; + req.address = address; if (addressType === 6) { err = self._handle.connect6(req, address, port); } else if (addressType === 4) { err = self._handle.connect(req, address, port); } } else { + req.address = address; err = self._handle.connect(req, address, afterConnect); } if (err) { - self._destroy(errnoException(err, 'connect')); + var details = util.format('%s:%s', address, port || ''); + var additions = { + address: address + }; + if (port) additions.port = port; + var ex = errnoException(err, 'connect', details, additions); + self._destroy(ex); } } @@ -896,6 +916,7 @@ Socket.prototype.connect = function(options, cb) { // There are no event listeners registered yet so defer the // error event to the next tick. process.nextTick(function() { + if (options.port) err.port = options.port; self.emit('error', err); self._destroy(); }); @@ -963,7 +984,13 @@ function afterConnect(status, handle, req, readable, writable) { } else { self._connecting = false; - self._destroy(errnoException(status, 'connect')); + var details = util.format('%s:%s', req.address, req.port || ''); + var additions = { + address: req.address + }; + if (req.port) additions.port = req.port; + var ex = errnoException(status, 'connect', details, additions); + self._destroy(ex); } } @@ -1104,7 +1131,12 @@ Server.prototype._listen2 = function(address, port, addressType, backlog, fd) { debug('_listen2: create a handle'); var rval = createServerHandle(address, port, addressType, fd); if (util.isNumber(rval)) { - var error = errnoException(rval, 'listen'); + var details = util.format('%s:%s', address, port > 0 ? port : ''); + var additions = { + address: address + }; + if (port > 0) additions.port = port; + var error = errnoException(rval, 'listen', details, additions); process.nextTick(function() { self.emit('error', error); }); @@ -1124,7 +1156,12 @@ Server.prototype._listen2 = function(address, port, addressType, backlog, fd) { err = _listen(self._handle, backlog); if (err) { - var ex = errnoException(err, 'listen'); + var details = util.format('%s:%s', address, port > 0 ? port : ''); + var additions = { + address: address + }; + if (port > 0) additions.port = port; + var ex = errnoException(err, 'listen', details, additions); self._handle.close(); self._handle = null; process.nextTick(function() { @@ -1170,8 +1207,16 @@ function listen(self, address, port, addressType, backlog, fd) { err = uv.UV_EADDRINUSE; } - if (err) - return self.emit('error', errnoException(err, 'bind')); + if (err) { + var details = util.format('%s:%s', address, port > 0 ? port : ''); + var additions = { + address: address + }; + if (port > 0) additions.port = port; + var ex = errnoException(err, 'bind', details, additions); + return self.emit('error', ex); + } + self._handle = handle; self._listen2(address, port, addressType, backlog, fd); diff --git a/lib/util.js b/lib/util.js index 2de944586fea..3ffae8fb55c5 100644 --- a/lib/util.js +++ b/lib/util.js @@ -733,7 +733,7 @@ exports.pump = exports.deprecate(function(readStream, writeStream, callback) { var uv; -exports._errnoException = function(err, syscall, original) { +exports._errnoException = function(err, syscall, original, additions) { if (isUndefined(uv)) uv = process.binding('uv'); var errname = uv.errname(err); var message = syscall + ' ' + errname; @@ -743,5 +743,7 @@ exports._errnoException = function(err, syscall, original) { e.code = errname; e.errno = errname; e.syscall = syscall; + if (additions) + e = exports._extend(e, additions); return e; }; diff --git a/test/simple/test-net-better-error-messages-listen-path.js b/test/simple/test-net-better-error-messages-listen-path.js new file mode 100644 index 000000000000..32f949621a3e --- /dev/null +++ b/test/simple/test-net-better-error-messages-listen-path.js @@ -0,0 +1,39 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var common = require('../common'); +var assert = require('assert'); +var net = require('net'); +var gotError = false; +var fp = '/blah/fadfa'; +var server = net.createServer(function(socket) { +}); +server.listen(fp, function() { + assert(false); +}); +server.on('error', function(e) { + console.error('error', e); + gotError = true; +}); + +process.on('exit', function() { + assert(gotError); +}); diff --git a/test/simple/test-net-better-error-messages-listen.js b/test/simple/test-net-better-error-messages-listen.js new file mode 100644 index 000000000000..268ea6efc300 --- /dev/null +++ b/test/simple/test-net-better-error-messages-listen.js @@ -0,0 +1,41 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var common = require('../common'); +var assert = require('assert'); +var net = require('net'); +var gotError = false; + +var server = net.createServer(function(socket) { +}); +server.listen(1, '1.1.1.1', function() { // EACCESS or EADDRNOTAVAIL + assert(false); +}); +server.on('error', function(e) { + console.error('error', e); + gotError = true; + assert.equal('1.1.1.1', e.address); + assert.equal(1, e.port); +}); + +process.on('exit', function() { + assert(gotError); +}); diff --git a/test/simple/test-net-better-error-messages-path.js b/test/simple/test-net-better-error-messages-path.js new file mode 100644 index 000000000000..45993fd6125d --- /dev/null +++ b/test/simple/test-net-better-error-messages-path.js @@ -0,0 +1,45 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +var common = require('../common'); +var net = require('net'); +var assert = require('assert'); +var fp = '/tmp/fadagagsdfgsdf'; +var c = net.connect(fp); + +c.on('connect', function() { + console.error('connected?!'); + assert.ok(false); +}); + +var gotError = false; +c.on('error', function(e) { + console.error('couldn\'t connect.', e); + gotError = true; + assert.equal('ENOENT', e.code); + assert.equal(fp, e.address); +}); + +process.on('exit', function() { + assert.ok(gotError); +}); diff --git a/test/simple/test-net-better-error-messages-port-hostname.js b/test/simple/test-net-better-error-messages-port-hostname.js new file mode 100644 index 000000000000..75f23767c1c7 --- /dev/null +++ b/test/simple/test-net-better-error-messages-port-hostname.js @@ -0,0 +1,46 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +var common = require('../common'); +var net = require('net'); +var assert = require('assert'); + +var c = net.createConnection(common.PORT, 'blah'); + +c.on('connect', function() { + console.error('connected?!'); + assert.ok(false); +}); + +var gotError = false; +c.on('error', function(e) { + console.error('couldn\'t connect.', e); + gotError = true; + assert.equal('ENOTFOUND', e.code); + assert.equal(common.PORT, e.port); + assert.equal('blah', e.hostname); +}); + +process.on('exit', function() { + assert.ok(gotError); +}); diff --git a/test/simple/test-net-better-error-messages-port.js b/test/simple/test-net-better-error-messages-port.js new file mode 100644 index 000000000000..dabe01e93757 --- /dev/null +++ b/test/simple/test-net-better-error-messages-port.js @@ -0,0 +1,46 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +var common = require('../common'); +var net = require('net'); +var assert = require('assert'); + +var c = net.createConnection(common.PORT); + +c.on('connect', function() { + console.error('connected?!'); + assert.ok(false); +}); + +var gotError = false; +c.on('error', function(e) { + console.error('couldn\'t connect.', e); + gotError = true; + assert.equal('ECONNREFUSED', e.code); + assert.equal(common.PORT, e.port); + assert.equal('127.0.0.1', e.address); +}); + +process.on('exit', function() { + assert.ok(gotError); +});