From 50fe51ca3251f13e8f93325cca841e2252fc0961 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Wed, 3 Apr 2019 17:34:35 -0700 Subject: [PATCH] blockstore: close file if write or read throws --- lib/blockstore/file.js | 20 ++++++++++---- test/blockstore-test.js | 61 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 5 deletions(-) diff --git a/lib/blockstore/file.js b/lib/blockstore/file.js index 0f6f2c7b..02733336 100644 --- a/lib/blockstore/file.js +++ b/lib/blockstore/file.js @@ -383,10 +383,15 @@ class FileBlockStore extends AbstractBlockStore { const fd = await fs.open(filepath, 'r+'); - const mwritten = await fs.write(fd, magic, 0, mlength, mposition); - const bwritten = await fs.write(fd, data, 0, blength, bposition); + let mwritten = 0; + let bwritten = 0; - await fs.close(fd); + try { + mwritten = await fs.write(fd, magic, 0, mlength, mposition); + bwritten = await fs.write(fd, data, 0, blength, bposition); + } finally { + await fs.close(fd); + } if (mwritten !== mlength) { this.writing = false; @@ -480,8 +485,13 @@ class FileBlockStore extends AbstractBlockStore { const data = Buffer.alloc(length); const fd = await fs.open(filepath, 'r'); - const bytes = await fs.read(fd, data, 0, length, position); - await fs.close(fd); + let bytes = 0; + + try { + bytes = await fs.read(fd, data, 0, length, position); + } finally { + await fs.close(fd); + } if (bytes !== length) throw new Error('Wrong number of bytes read.'); diff --git a/test/blockstore-test.js b/test/blockstore-test.js index d15c51dc..048c438b 100644 --- a/test/blockstore-test.js +++ b/test/blockstore-test.js @@ -504,6 +504,41 @@ describe('BlockStore', function() { assert(err, 'Expected error.'); assert.equal(err.message, 'Could not write block.'); }); + + it('will close file if write throws', async () => { + let err = null; + let closed = null; + + store.allocate = () => { + return { + fileno: 20, + filerecord: { + used: 0 + }, + filepath: '/tmp/.bcoin/blocks/blk00020.dat' + }; + }; + store.db.has = () => false; + fs.open = () => 7; + fs.close = (fd) => { + closed = fd; + }; + fs.write = () => { + throw new Error('Test.'); + }; + + try { + const hash = random.randomBytes(128); + const block = random.randomBytes(32); + await store.write(hash, block); + } catch (e) { + err = e; + } + + assert(err, 'Expected error.'); + assert.equal(err.message, 'Test.'); + assert.equal(closed, 7); + }); }); describe('read', function() { @@ -553,6 +588,32 @@ describe('BlockStore', function() { assert(err, 'Expected error.'); assert.equal(err.message, 'Wrong number of bytes read.'); }); + + it('will close file if read throws', async () => { + let err = null; + let closed = null; + + store.db.get = () => raw; + fs.open = () => 7; + fs.close = (fd) => { + closed = fd; + }; + fs.read = () => { + throw new Error('Test.'); + }; + + try { + const hash = random.randomBytes(128); + const block = random.randomBytes(32); + await store.read(hash, block); + } catch (e) { + err = e; + } + + assert(err, 'Expected error.'); + assert.equal(err.message, 'Test.'); + assert.equal(closed, 7); + }); }); });