From 03738183c74d0be43846f96562cb89dce929a953 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Thu, 19 Sep 2013 06:38:37 +0200 Subject: [PATCH] dns: fix c-ares error reporting regression The test case from the previous commit exposed a regression in the way that c-ares errors are reported to JS land. Said regression was introduced in commit 756b622 ("src: add multi-context support"). Fixes the following test failure: $ out/Release/node test/simple/test-dns-regress-6244 util.js:675 var errname = uv.errname(err); ^ Error: err >= 0 at Object.exports._errnoException (util.js:675:20) at errnoException (dns.js:43:15) at Object.onresolve [as oncomplete] (dns.js:145:19) lib/dns.js erroneously assumed that the error code was a libuv error code when it's really a c-ares status code. Libuv handles getaddrinfo() style lookups (which is by far the most common type of lookup), that's why this bug wasn't discovered earlier. --- lib/dns.js | 9 ++++++--- src/cares_wrap.cc | 44 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/lib/dns.js b/lib/dns.js index dd274825b2a..3e4b90f6e3f 100644 --- a/lib/dns.js +++ b/lib/dns.js @@ -34,9 +34,12 @@ function errnoException(err, syscall) { 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'; + err = 'ENOTFOUND'; + } + if (typeof err === 'string') { // c-ares error code. + var ex = new Error(syscall + ' ' + err); + ex.code = err; + ex.errno = err; ex.syscall = syscall; return ex; } diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index 00238788ade..fd25a29e99b 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -313,14 +313,42 @@ class QueryWrap { assert(status != ARES_SUCCESS); Context::Scope context_scope(env()->context()); HandleScope handle_scope(env()->isolate()); - Local argv[] = { - Integer::New(status, env()->isolate()) - }; - MakeCallback(env(), - object(), - env()->oncomplete_string(), - ARRAY_SIZE(argv), - argv); + Local arg; + switch (status) { +#define V(code) \ + case ARES_ ## code: \ + arg = FIXED_ONE_BYTE_STRING(env()->isolate(), #code); \ + break; + V(ENODATA) + V(EFORMERR) + V(ESERVFAIL) + V(ENOTFOUND) + V(ENOTIMP) + V(EREFUSED) + V(EBADQUERY) + V(EBADNAME) + V(EBADFAMILY) + V(EBADRESP) + V(ECONNREFUSED) + V(ETIMEOUT) + V(EOF) + V(EFILE) + V(ENOMEM) + V(EDESTRUCTION) + V(EBADSTR) + V(EBADFLAGS) + V(ENONAME) + V(EBADHINTS) + V(ENOTINITIALIZED) + V(ELOADIPHLPAPI) + V(EADDRGETNETWORKPARAMS) + V(ECANCELLED) +#undef V + default: + arg = FIXED_ONE_BYTE_STRING(env()->isolate(), "UNKNOWN_ARES_ERROR"); + break; + } + MakeCallback(env(), object(), env()->oncomplete_string(), 1, &arg); } // Subclasses should implement the appropriate Parse method.