Skip to content

Commit

Permalink
fs: throw fs.fstat{Sync} errors in JS
Browse files Browse the repository at this point in the history
PR-URL: #17914
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
joyeecheung committed Jan 16, 2018
1 parent da7804f commit 8c00a80
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 19 deletions.
17 changes: 10 additions & 7 deletions lib/fs.js
Expand Up @@ -633,12 +633,11 @@ function readFileAfterClose(err) {
}

function tryStatSync(fd, isUserFd) {
var threw = true;
try {
binding.fstat(fd);
threw = false;
} finally {
if (threw && !isUserFd) fs.closeSync(fd);
const ctx = {};
binding.fstat(fd, undefined, ctx);
if (ctx.errno !== undefined && !isUserFd) {
fs.closeSync(fd);
throw new errors.uvException(ctx);
}
}

Expand Down Expand Up @@ -1115,7 +1114,11 @@ fs.stat = function(path, callback) {

fs.fstatSync = function(fd) {
validateUint32(fd, 'fd');
binding.fstat(fd);
const ctx = { fd };
binding.fstat(fd, undefined, ctx);
if (ctx.errno !== undefined) {
throw new errors.uvException(ctx);
}
return statsFromValues();
};

Expand Down
15 changes: 10 additions & 5 deletions src/node_file.cc
Expand Up @@ -587,19 +587,24 @@ static void LStat(const FunctionCallbackInfo<Value>& args) {

static void FStat(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
Local<Context> context = env->context();

CHECK(args[0]->IsInt32());

int fd = args[0]->Int32Value();
int fd = static_cast<int>(args[0]->Int32Value(context).FromJust());

if (args[1]->IsObject()) { // fstat(fd, req)
CHECK_EQ(args.Length(), 2);
AsyncCall(env, args, "fstat", UTF8, AfterStat,
uv_fs_fstat, fd);
} else { // fstat(fd)
SYNC_CALL(fstat, nullptr, fd)
FillStatsArray(env->fs_stats_field_array(),
static_cast<const uv_stat_t*>(SYNC_REQ.ptr));
} else { // fstat(fd, undefined, ctx)
CHECK_EQ(args.Length(), 3);
fs_req_wrap req_wrap;
int err = SyncCall(env, args[2], &req_wrap, "fstat", uv_fs_fstat, fd);
if (err == 0) {
FillStatsArray(env->fs_stats_field_array(),
static_cast<const uv_stat_t*>(req_wrap.req.ptr));
}
}
}

Expand Down
16 changes: 9 additions & 7 deletions test/parallel/test-fs-sync-fd-leak.js
Expand Up @@ -23,6 +23,7 @@
require('../common');
const assert = require('assert');
const fs = require('fs');
const uv = process.binding('uv');

// ensure that (read|write|append)FileSync() closes the file descriptor
fs.openSync = function() {
Expand All @@ -39,29 +40,30 @@ fs.writeSync = function() {
throw new Error('BAM');
};

process.binding('fs').fstat = function() {
throw new Error('BAM');
process.binding('fs').fstat = function(fd, _, ctx) {
ctx.errno = uv.UV_EBADF;
ctx.syscall = 'fstat';
};

let close_called = 0;
ensureThrows(function() {
fs.readFileSync('dummy');
});
}, 'EBADF: bad file descriptor, fstat');
ensureThrows(function() {
fs.writeFileSync('dummy', 'xxx');
});
}, 'BAM');
ensureThrows(function() {
fs.appendFileSync('dummy', 'xxx');
});
}, 'BAM');

function ensureThrows(cb) {
function ensureThrows(cb, message) {
let got_exception = false;

close_called = 0;
try {
cb();
} catch (e) {
assert.strictEqual(e.message, 'BAM');
assert.strictEqual(e.message, message);
got_exception = true;
}

Expand Down

0 comments on commit 8c00a80

Please sign in to comment.