From b5391bd4eea8a8d6ceaa9375ce6d64891a331c26 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Fri, 18 Sep 2015 21:45:38 +0200 Subject: [PATCH] fs: don't fail with EBADF on double close Calling fs.ReadStream#close() or fs.WriteStream#close() twice made it try to close the file descriptor twice, with the second attempt using the nulled out `.fd` property and failing with an EBADF error. Fixes: https://github.com/nodejs/node/issues/2950 --- lib/fs.js | 2 ++ test/parallel/test-fs-read-stream-double-close.js | 11 +++++++++++ test/parallel/test-fs-write-stream-double-close.js | 10 ++++++++++ 3 files changed, 23 insertions(+) create mode 100644 test/parallel/test-fs-read-stream-double-close.js create mode 100644 test/parallel/test-fs-write-stream-double-close.js diff --git a/lib/fs.js b/lib/fs.js index 76f53db9ba7ec4..b405c88d9ad0a3 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -1770,6 +1770,8 @@ ReadStream.prototype.close = function(cb) { close(); function close(fd) { + if (fd === undefined && self.fd === null) + return; fs.close(fd || self.fd, function(er) { if (er) self.emit('error', er); diff --git a/test/parallel/test-fs-read-stream-double-close.js b/test/parallel/test-fs-read-stream-double-close.js new file mode 100644 index 00000000000000..703f21145a94e1 --- /dev/null +++ b/test/parallel/test-fs-read-stream-double-close.js @@ -0,0 +1,11 @@ +'use strict'; + +const common = require('../common'); +const fs = require('fs'); + +common.refreshTmpDir(); +fs.writeFileSync(common.tmpDir + '/ro', ''); + +const s = fs.createReadStream(common.tmpDir + '/ro'); +s.close(common.mustCall(function() {})); +s.close(common.mustCall(function() {})); diff --git a/test/parallel/test-fs-write-stream-double-close.js b/test/parallel/test-fs-write-stream-double-close.js new file mode 100644 index 00000000000000..ca459012462ca1 --- /dev/null +++ b/test/parallel/test-fs-write-stream-double-close.js @@ -0,0 +1,10 @@ +'use strict'; + +const common = require('../common'); +const fs = require('fs'); + +common.refreshTmpDir(); + +const s = fs.createWriteStream(common.tmpDir + '/rw'); +s.close(common.mustCall(function() {})); +s.close(common.mustCall(function() {}));