From 2d9ab49239d475cad3126384daefc6f365555dd9 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Tue, 6 Sep 2011 02:03:43 +0200 Subject: [PATCH] file: fix errno propagation in sync fs calls Include libuv fs error code in the JS exception. Fixes #1657. --- src/node_file.cc | 67 +++++++++++++++++++++- test/simple/test-fs-open.js | 2 +- .../simple/test-net-connect-handle-econnrefused.js | 1 - 3 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/node_file.cc b/src/node_file.cc index f9e58b4..a523a93 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -213,6 +213,69 @@ struct fs_req_wrap { uv_fs_t req; }; + +const char* errno_string(int errorno) { + uv_err_t err; + memset(&err, 0, sizeof err); + err.code = (uv_err_code)errorno; + return uv_err_name(err); +} + + +const char* 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 in node.cc, tuned for uv errors +Local FSError(int errorno, + const char *syscall, + const char *msg, + const char *path) { + static Persistent syscall_symbol; + static Persistent errpath_symbol; + static Persistent code_symbol; + + if (syscall_symbol.IsEmpty()) { + syscall_symbol = NODE_PSYMBOL("syscall"); + errno_symbol = NODE_PSYMBOL("errno"); + errpath_symbol = NODE_PSYMBOL("path"); + code_symbol = NODE_PSYMBOL("code"); + } + + if (!msg || !msg[0]) + msg = errno_message(errorno); + + Local estring = String::NewSymbol(errno_string(errorno)); + Local message = String::NewSymbol(msg); + Local cons1 = String::Concat(estring, String::NewSymbol(", ")); + Local cons2 = String::Concat(cons1, message); + + Local e; + + if (path) { + Local cons3 = String::Concat(cons2, String::NewSymbol(" '")); + Local cons4 = String::Concat(cons3, String::New(path)); + Local cons5 = String::Concat(cons4, String::NewSymbol("'")); + e = Exception::Error(cons5); + } else { + e = Exception::Error(cons2); + } + + Local obj = e->ToObject(); + + // TODO errno should probably go + obj->Set(errno_symbol, Integer::New(errorno)); + obj->Set(code_symbol, estring); + if (path) obj->Set(errpath_symbol, String::New(path)); + if (syscall) obj->Set(syscall_symbol, String::NewSymbol(syscall)); + return e; +} + + #define ASYNC_CALL(func, callback, ...) \ FSReqWrap* req_wrap = new FSReqWrap(); \ int r = uv_fs_##func(uv_default_loop(), &req_wrap->req_, \ @@ -226,8 +289,8 @@ struct fs_req_wrap { fs_req_wrap req_wrap; \ uv_fs_##func(uv_default_loop(), &req_wrap.req, __VA_ARGS__, NULL); \ if (req_wrap.req.result < 0) { \ - return ThrowException( \ - ErrnoException(req_wrap.req.errorno, #func, "", path)); \ + int code = uv_last_error(uv_default_loop()).code; \ + return ThrowException(FSError(code, #func, "", path)); \ } #define SYNC_REQ req_wrap.req diff --git a/test/simple/test-fs-open.js b/test/simple/test-fs-open.js index d2c4f54..922c033 100644 --- a/test/simple/test-fs-open.js +++ b/test/simple/test-fs-open.js @@ -30,7 +30,7 @@ try { fs.openSync('/path/to/file/that/does/not/exist', 'r'); } catch (e) { - assert.equal(e.errno, constants.ENOENT); + assert.equal(e.code, 'ENOENT'); caughtException = true; } assert.ok(caughtException); diff --git a/test/simple/test-net-connect-handle-econnrefused.js b/test/simple/test-net-connect-handle-econnrefused.js index 6009998..4cced78 100644 --- a/test/simple/test-net-connect-handle-econnrefused.js +++ b/test/simple/test-net-connect-handle-econnrefused.js @@ -39,7 +39,6 @@ var gotError = false; c.on('error', function(e) { console.error('couldn\'t connect.'); gotError = true; - assert.equal(require('constants').ECONNREFUSED, e.errno); assert.equal('ECONNREFUSED', e.code); }); -- 2.7.4