Skip to content

Commit bb8ca7e

Browse files
committed
fix(Blockchain, Node, Wallet): prevent race conditions when closing a component while initializing
Errors could occur when a component was closed while still handling its initialization.
1 parent 532843d commit bb8ca7e

File tree

3 files changed

+35
-6
lines changed

3 files changed

+35
-6
lines changed

lib/blockchain.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,18 @@ Blockchain.prototype._initStore = function (cb) {
8787
async.parallel(tasks, cb)
8888
}
8989

90+
Blockchain.prototype.waitForReady = function (cb) {
91+
if (this.initialized) return cb()
92+
this.on('ready', cb)
93+
}
94+
9095
Blockchain.prototype.close = function (cb) {
91-
this.closed = true
92-
this.store.close(cb)
96+
var self = this
97+
this.waitForReady(function () {
98+
self.closed = true
99+
self.syncing = false
100+
self.store.close(cb)
101+
})
93102
}
94103

95104
Blockchain.prototype.sync = function (opts, cb) {
@@ -322,7 +331,7 @@ Blockchain.prototype._setDownloadPeer = function (peer) {
322331
Blockchain.prototype._getHeaders = function (opts) {
323332
var self = this
324333

325-
if (!this.syncing || this.closed) return
334+
if (!this.syncing) return
326335
if (!this.downloadPeer) {
327336
this._findDownloadPeer(function (err, peer) {
328337
if (err) return self._error(err)

lib/node.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ var Node = module.exports = function (opts, cb) {
3838

3939
this.wallets = {}
4040

41+
this.closing = false
42+
this.closed = false
43+
4144
if (cb) this.start(cb)
4245
}
4346
util.inherits(Node, EventEmitter)
@@ -57,6 +60,7 @@ Node.prototype.close = function (cb) {
5760
if (!cb) cb = function () {}
5861
var self = this
5962

63+
this.closing = true
6064
this.peers.disconnect()
6165

6266
var wallets = []
@@ -66,6 +70,7 @@ Node.prototype.close = function (cb) {
6670

6771
self.chain.close(function (err) {
6872
if (err) return cb(err)
73+
this.closed = true
6974
self.emit('end')
7075
cb(null)
7176
})
@@ -137,7 +142,9 @@ Node.prototype._sendHeaders = function (peer, message) {
137142
}
138143
})
139144
}, function (err) {
140-
if (err !== true) return self._error(err)
145+
if (err !== true && !(err.message === 'Database is not open' && self.closing)) {
146+
return self._error(err)
147+
}
141148
if (!start || !start.next) return
142149
self.chain.store.get(start.next, next)
143150
})

lib/wallet.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,17 @@ var Wallet = module.exports = function (opts, cb) {
5151
this.feePerKb = opts.feePerKb || 10000
5252

5353
this._error = this._error.bind(this)
54+
this.initialized = false
5455
this._initialize(cb)
5556
}
5657
util.inherits(Wallet, EventEmitter)
5758

5859
Wallet.prototype.close = function (cb) {
59-
this.closed = true
60-
this.store.close(cb)
60+
var self = this
61+
this.waitForReady(function () {
62+
self.closed = true
63+
self.store.close(cb)
64+
})
6165
}
6266

6367
Wallet.prototype.getKey = function () {
@@ -159,11 +163,17 @@ Wallet.prototype._initialize = function (cb) {
159163
], function (err, res) {
160164
if (err) return (cb || self._error)(err)
161165
self._listenToChain()
166+
self.initialized = true
162167
self.emit('ready')
163168
if (cb) cb(null)
164169
})
165170
}
166171

172+
Wallet.prototype.waitForReady = function (cb) {
173+
if (this.initialized) return cb()
174+
this.on('ready', cb)
175+
}
176+
167177
Wallet.prototype._listenToChain = function () {
168178
var self = this
169179
if (this.peers.numberConnected() === 0) {
@@ -243,6 +253,9 @@ Wallet.prototype._scanChain = function (opts) {
243253
self.emit('synced')
244254
})
245255
})
256+
txs.blocks.on('data', function (block) {
257+
self.emit('sync', block)
258+
})
246259
}
247260
})
248261
}

0 commit comments

Comments
 (0)