file: fix errno propagation in sync fs calls
Include libuv fs error code in the JS exception. Fixes #1657.
This commit is contained in:
parent
554dc63328
commit
2d9ab49239
@ -213,6 +213,69 @@ struct fs_req_wrap {
|
|||||||
uv_fs_t req;
|
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<Value> FSError(int errorno,
|
||||||
|
const char *syscall,
|
||||||
|
const char *msg,
|
||||||
|
const char *path) {
|
||||||
|
static Persistent<String> syscall_symbol;
|
||||||
|
static Persistent<String> errpath_symbol;
|
||||||
|
static Persistent<String> 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<String> estring = String::NewSymbol(errno_string(errorno));
|
||||||
|
Local<String> message = String::NewSymbol(msg);
|
||||||
|
Local<String> cons1 = String::Concat(estring, String::NewSymbol(", "));
|
||||||
|
Local<String> cons2 = String::Concat(cons1, message);
|
||||||
|
|
||||||
|
Local<Value> e;
|
||||||
|
|
||||||
|
if (path) {
|
||||||
|
Local<String> cons3 = String::Concat(cons2, String::NewSymbol(" '"));
|
||||||
|
Local<String> cons4 = String::Concat(cons3, String::New(path));
|
||||||
|
Local<String> cons5 = String::Concat(cons4, String::NewSymbol("'"));
|
||||||
|
e = Exception::Error(cons5);
|
||||||
|
} else {
|
||||||
|
e = Exception::Error(cons2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Local<Object> 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, ...) \
|
#define ASYNC_CALL(func, callback, ...) \
|
||||||
FSReqWrap* req_wrap = new FSReqWrap(); \
|
FSReqWrap* req_wrap = new FSReqWrap(); \
|
||||||
int r = uv_fs_##func(uv_default_loop(), &req_wrap->req_, \
|
int r = uv_fs_##func(uv_default_loop(), &req_wrap->req_, \
|
||||||
@ -226,8 +289,8 @@ struct fs_req_wrap {
|
|||||||
fs_req_wrap req_wrap; \
|
fs_req_wrap req_wrap; \
|
||||||
uv_fs_##func(uv_default_loop(), &req_wrap.req, __VA_ARGS__, NULL); \
|
uv_fs_##func(uv_default_loop(), &req_wrap.req, __VA_ARGS__, NULL); \
|
||||||
if (req_wrap.req.result < 0) { \
|
if (req_wrap.req.result < 0) { \
|
||||||
return ThrowException( \
|
int code = uv_last_error(uv_default_loop()).code; \
|
||||||
ErrnoException(req_wrap.req.errorno, #func, "", path)); \
|
return ThrowException(FSError(code, #func, "", path)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SYNC_REQ req_wrap.req
|
#define SYNC_REQ req_wrap.req
|
||||||
|
@ -30,7 +30,7 @@ try {
|
|||||||
fs.openSync('/path/to/file/that/does/not/exist', 'r');
|
fs.openSync('/path/to/file/that/does/not/exist', 'r');
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
assert.equal(e.errno, constants.ENOENT);
|
assert.equal(e.code, 'ENOENT');
|
||||||
caughtException = true;
|
caughtException = true;
|
||||||
}
|
}
|
||||||
assert.ok(caughtException);
|
assert.ok(caughtException);
|
||||||
|
@ -39,7 +39,6 @@ var gotError = false;
|
|||||||
c.on('error', function(e) {
|
c.on('error', function(e) {
|
||||||
console.error('couldn\'t connect.');
|
console.error('couldn\'t connect.');
|
||||||
gotError = true;
|
gotError = true;
|
||||||
assert.equal(require('constants').ECONNREFUSED, e.errno);
|
|
||||||
assert.equal('ECONNREFUSED', e.code);
|
assert.equal('ECONNREFUSED', e.code);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user