cleanup daemon

This commit is contained in:
Patrick Nagurny 2015-08-21 11:53:20 -04:00
parent a61e1d9b8f
commit 164a2cad75
5 changed files with 41 additions and 186 deletions

View File

@ -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}));

View File

@ -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;

View File

@ -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) {

View File

@ -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<Boolean>(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<Boolean>(shutdown_complete));
}
/**
* GetBlock()
* bitcoind.getBlock([blockhash,blockheight], callback)
@ -1650,8 +1626,6 @@ init(Handle<Object> 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);

View File

@ -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);