Skip to content

Commit

Permalink
fix(Blockchain, Node, Wallet): prevent race conditions when closing a…
Browse files Browse the repository at this point in the history
… component while initializing

Errors could occur when a component was closed while still handling its initialization.
  • Loading branch information
mappum committed Jun 25, 2015
1 parent 532843d commit bb8ca7e
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 6 deletions.
15 changes: 12 additions & 3 deletions lib/blockchain.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,18 @@ Blockchain.prototype._initStore = function (cb) {
async.parallel(tasks, cb)
}

Blockchain.prototype.waitForReady = function (cb) {
if (this.initialized) return cb()
this.on('ready', cb)
}

Blockchain.prototype.close = function (cb) {
this.closed = true
this.store.close(cb)
var self = this
this.waitForReady(function () {
self.closed = true
self.syncing = false
self.store.close(cb)
})
}

Blockchain.prototype.sync = function (opts, cb) {
Expand Down Expand Up @@ -322,7 +331,7 @@ Blockchain.prototype._setDownloadPeer = function (peer) {
Blockchain.prototype._getHeaders = function (opts) {
var self = this

if (!this.syncing || this.closed) return
if (!this.syncing) return
if (!this.downloadPeer) {
this._findDownloadPeer(function (err, peer) {
if (err) return self._error(err)
Expand Down
9 changes: 8 additions & 1 deletion lib/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ var Node = module.exports = function (opts, cb) {

this.wallets = {}

this.closing = false
this.closed = false

if (cb) this.start(cb)
}
util.inherits(Node, EventEmitter)
Expand All @@ -57,6 +60,7 @@ Node.prototype.close = function (cb) {
if (!cb) cb = function () {}
var self = this

this.closing = true
this.peers.disconnect()

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

self.chain.close(function (err) {
if (err) return cb(err)
this.closed = true
self.emit('end')
cb(null)
})
Expand Down Expand Up @@ -137,7 +142,9 @@ Node.prototype._sendHeaders = function (peer, message) {
}
})
}, function (err) {
if (err !== true) return self._error(err)
if (err !== true && !(err.message === 'Database is not open' && self.closing)) {
return self._error(err)
}
if (!start || !start.next) return
self.chain.store.get(start.next, next)
})
Expand Down
17 changes: 15 additions & 2 deletions lib/wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,17 @@ var Wallet = module.exports = function (opts, cb) {
this.feePerKb = opts.feePerKb || 10000

this._error = this._error.bind(this)
this.initialized = false
this._initialize(cb)
}
util.inherits(Wallet, EventEmitter)

Wallet.prototype.close = function (cb) {
this.closed = true
this.store.close(cb)
var self = this
this.waitForReady(function () {
self.closed = true
self.store.close(cb)
})
}

Wallet.prototype.getKey = function () {
Expand Down Expand Up @@ -159,11 +163,17 @@ Wallet.prototype._initialize = function (cb) {
], function (err, res) {
if (err) return (cb || self._error)(err)
self._listenToChain()
self.initialized = true
self.emit('ready')
if (cb) cb(null)
})
}

Wallet.prototype.waitForReady = function (cb) {
if (this.initialized) return cb()
this.on('ready', cb)
}

Wallet.prototype._listenToChain = function () {
var self = this
if (this.peers.numberConnected() === 0) {
Expand Down Expand Up @@ -243,6 +253,9 @@ Wallet.prototype._scanChain = function (opts) {
self.emit('synced')
})
})
txs.blocks.on('data', function (block) {
self.emit('sync', block)
})
}
})
}
Expand Down

0 comments on commit bb8ca7e

Please sign in to comment.