From 164a2cad75c1ecacbf722a787c9e01733ea67ae2 Mon Sep 17 00:00:00 2001 From: Patrick Nagurny Date: Fri, 21 Aug 2015 11:53:20 -0400 Subject: [PATCH] cleanup daemon --- bin/start.js | 17 +++++ lib/daemon.js | 167 +++++---------------------------------------- lib/node.js | 15 ++-- src/libbitcoind.cc | 26 ------- src/libbitcoind.h | 2 - 5 files changed, 41 insertions(+), 186 deletions(-) diff --git a/bin/start.js b/bin/start.js index 9b9f716a..72f8dd04 100644 --- a/bin/start.js +++ b/bin/start.js @@ -142,6 +142,10 @@ node.chain.on('addblock', function(block) { } }); +node.on('stopping', function() { + clearInterval(interval); +}); + process.stdin.resume();//so the program will not close instantly function exitHandler(options, err) { @@ -169,5 +173,18 @@ function exitHandler(options, err) { //catches ctrl+c event process.on('SIGINT', exitHandler.bind(null, {sigint:true})); +/*setTimeout(function() { + log.info('Stopping Services'); + node.stop(function(err) { + if(err) { + log.error('Failed to stop services: ' + err); + return process.exit(1); + } + + log.info('Halted'); + process.exit(0); + }); +}, 10000);*/ + //catches uncaught exceptions process.on('uncaughtException', exitHandler.bind(null, {exit:true})); diff --git a/lib/daemon.js b/lib/daemon.js index 23cc18d0..54717ad3 100644 --- a/lib/daemon.js +++ b/lib/daemon.js @@ -33,29 +33,10 @@ function Daemon(options) { self[key] = exports[key]; }); - this.on('newListener', function(name) { - if (name === 'open') { - //self.start(); - } - }); } util.inherits(Daemon, EventEmitter); -// Make sure signal handlers are not overwritten -Daemon._signalQueue = []; -Daemon._processOn = process.on; -process.addListener = -process.on = function(name, listener) { - if (~['SIGINT', 'SIGHUP', 'SIGQUIT'].indexOf(name.toUpperCase())) { - if (!Daemon.global || !Daemon.global._started) { - Daemon._signalQueue.push([name, listener]); - return; - } - } - return Daemon._processOn.apply(this, arguments); -}; - Daemon.instances = {}; Daemon.prototype.instances = Daemon.instances; @@ -71,77 +52,17 @@ Daemon.prototype.start = function(callback) { var self = this; if (this.instances[this.datadir]) { - return; + return callback(new Error('Daemon already started')); } this.instances[this.datadir] = true; - var none = {}; - var isSignal = {}; - var sigint = { name: 'SIGINT', signal: isSignal }; - var sighup = { name: 'SIGHUP', signal: isSignal }; - var sigquit = { name: 'SIGQUIT', signal: isSignal }; - var exitCaught = none; - var errorCaught = none; - - Object.keys(this.options).forEach(function(key) { - if (self.options[key] == null) { - self.options[key] = self.options[key]; + bitcoind.start(this.options, function(err) { + if(err) { + return callback(err); } - }); - bitcoind.start(this.options, function(err, status) { self._started = true; - // Poll for queued packet - [sigint, sighup, sigquit].forEach(function(signal) { - process.on(signal.name, signal.listener = function() { - if (process.listeners(signal.name).length > 1) { - return; - } - if (!self._shutdown) { - process.exit(0); - } else { - self.stop(); - exitCaught = signal; - } - }); - }); - - // Finally set signal handlers - process.on = process.addListener = Daemon._processOn; - Daemon._signalQueue.forEach(function(event) { - process.on(event[0], event[1]); - }); - - var exit = process.exit; - self._exit = function() { - return exit.apply(process, arguments); - }; - - process.exit = function(code) { - exitCaught = code || 0; - if (!self._shutdown) { - return self._exit(code); - } - self.stop(); - }; - - process.on('uncaughtException', function(err) { - if (process.listeners('uncaughtException').length > 1) { - return; - } - errorCaught = err; - log.error('Uncaught error: shutting down safely before throwing...'); - if (!self._shutdown) { - if (err && err.stack) { - log.error(err.stack); - } - self._exit(1); - return; - } - self.stop(); - }); - bitcoind.onBlocksReady(function(err, result) { function onTipUpdateListener(result) { @@ -155,58 +76,18 @@ Daemon.prototype.start = function(callback) { bitcoind.onTipUpdate(onTipUpdateListener); - self.emit('ready', result); - bitcoind.startTxMon(function(txs) { for(var i = 0; i < txs.length; i++) { self.emit('tx', txs[i]); } }); - }); - - setTimeout(function callee() { - if (err) { - self.emit('error', err); - callback(err); - } else { - self.emit('open', status); + setImmediate(function() { + self.emit('ready', result); callback(); - } - }, 100); + }); + }); }); - - // bitcoind's boost threads aren't in the thread pool - // or on node's event loop, so we need to keep node open. - this._shutdown = setInterval(function() { - if (!self._stoppingSaid && bitcoind.stopping()) { - self._stoppingSaid = true; - } - - if (bitcoind.stopped()) { - - clearInterval(self._shutdown); - delete self._shutdown; - - if (exitCaught !== none) { - if (exitCaught.signal === isSignal) { - process.removeListener(exitCaught.name, exitCaught.listener); - setImmediate(function() { - process.kill(process.pid, exitCaught.name); - }); - return; - } - return self._exit(exitCaught); - } - - if (errorCaught !== none) { - if (errorCaught && errorCaught.stack) { - log.error(errorCaught.stack); - } - return self._exit(0); - } - } - }, 1000); }; Daemon.prototype.isSynced = function() { @@ -258,33 +139,17 @@ Daemon.prototype.getInfo = function() { }; Daemon.prototype.stop = function(callback) { - if (Daemon.stopping) return []; var self = this; return bitcoind.stop(function(err, status) { - if (err) { - self.error(err.message); - } else { - log.info(status); - } - if (!callback) return; - return callback(err, status); + setImmediate(function() { + if (err) { + return callback(err); + } else { + log.info(status); + return callback(); + } + }); }); }; -Daemon.prototype.__defineGetter__('stopping', function() { - return bitcoind.stopping() || bitcoind.stopped(); -}); - -Daemon.prototype.__defineGetter__('stopped', function() { - return bitcoind.stopped(); -}); - -Daemon.__defineGetter__('stopping', function() { - return bitcoind.stopping() || bitcoind.stopped(); -}); - -Daemon.__defineGetter__('stopped', function() { - return bitcoind.stopped(); -}); - module.exports = Daemon; diff --git a/lib/node.js b/lib/node.js index d3f5c804..30466269 100644 --- a/lib/node.js +++ b/lib/node.js @@ -236,12 +236,13 @@ Node.prototype._syncBitcoind = function() { async.whilst(function() { height = self.chain.tip.__height; - return height < self.bitcoindHeight; + return height < self.bitcoindHeight && !self.stopping; }, function(done) { self.bitcoind.getBlock(height + 1, function(err, blockBuffer) { if (err) { return done(err); } + var block = self.Block.fromBuffer(blockBuffer); if (block.prevHash === self.chain.tip.hash) { @@ -259,17 +260,17 @@ Node.prototype._syncBitcoind = function() { if (err) { return done(err); } + delete self.chain.tip.__transactions; self.chain.tip = block; log.debug('Saving metadata'); self.chain.saveMetadata(); log.debug('Chain added block to main chain'); self.chain.emit('addblock', block); - done(); + setImmediate(done); }); } else { - // This block doesn't progress the current tip, so we'll attempt // to rewind the chain to the common ancestor of the block and // then we can resume syncing. @@ -397,10 +398,6 @@ Node.prototype._initialize = function() { self.bitcoindHeight = info.blocks; }); - this.bitcoind.on('open', function(status) { - log.info('Bitcoin Core Daemon Status:', status); - }); - // Notify that there is a new tip this.bitcoind.on('tip', function(height) { var percentage = self.bitcoind.syncPercentage(); @@ -481,9 +478,13 @@ Node.prototype.start = function(callback) { }; Node.prototype.stop = function(callback) { + log.info('Stopping Bitcore Node'); var self = this; var services = this.getServiceOrder().reverse(); + this.stopping = true; + this.emit('stopping'); + async.eachSeries( services, function(service, next) { diff --git a/src/libbitcoind.cc b/src/libbitcoind.cc index f2fce2ac..5c3c0add 100644 --- a/src/libbitcoind.cc +++ b/src/libbitcoind.cc @@ -885,30 +885,6 @@ async_stop_node_after(uv_work_t *req) { delete req; } -/** - * IsStopping() - * bitcoind.stopping() - * Check whether bitcoind is in the process of shutting down. This is polled - * from javascript. - */ - -NAN_METHOD(IsStopping) { - NanScope(); - NanReturnValue(NanNew(ShutdownRequested())); -} - -/** - * IsStopped() - * bitcoind.stopped() - * Check whether bitcoind has shutdown completely. This will be polled by - * javascript to check whether the libuv event loop is safe to stop. - */ - -NAN_METHOD(IsStopped) { - NanScope(); - NanReturnValue(NanNew(shutdown_complete)); -} - /** * GetBlock() * bitcoind.getBlock([blockhash,blockheight], callback) @@ -1650,8 +1626,6 @@ init(Handle target) { NODE_SET_METHOD(target, "onBlocksReady", OnBlocksReady); NODE_SET_METHOD(target, "onTipUpdate", OnTipUpdate); NODE_SET_METHOD(target, "stop", StopBitcoind); - NODE_SET_METHOD(target, "stopping", IsStopping); - NODE_SET_METHOD(target, "stopped", IsStopped); NODE_SET_METHOD(target, "getBlock", GetBlock); NODE_SET_METHOD(target, "getTransaction", GetTransaction); NODE_SET_METHOD(target, "getTransactionWithBlockInfo", GetTransactionWithBlockInfo); diff --git a/src/libbitcoind.h b/src/libbitcoind.h index 9744f828..e35e40b6 100644 --- a/src/libbitcoind.h +++ b/src/libbitcoind.h @@ -20,8 +20,6 @@ NAN_METHOD(StartBitcoind); NAN_METHOD(OnBlocksReady); NAN_METHOD(OnTipUpdate); -NAN_METHOD(IsStopping); -NAN_METHOD(IsStopped); NAN_METHOD(StopBitcoind); NAN_METHOD(GetBlock); NAN_METHOD(GetTransaction);