cleanup daemon
This commit is contained in:
parent
a61e1d9b8f
commit
164a2cad75
17
bin/start.js
17
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
|
process.stdin.resume();//so the program will not close instantly
|
||||||
|
|
||||||
function exitHandler(options, err) {
|
function exitHandler(options, err) {
|
||||||
@ -169,5 +173,18 @@ function exitHandler(options, err) {
|
|||||||
//catches ctrl+c event
|
//catches ctrl+c event
|
||||||
process.on('SIGINT', exitHandler.bind(null, {sigint:true}));
|
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
|
//catches uncaught exceptions
|
||||||
process.on('uncaughtException', exitHandler.bind(null, {exit:true}));
|
process.on('uncaughtException', exitHandler.bind(null, {exit:true}));
|
||||||
|
|||||||
167
lib/daemon.js
167
lib/daemon.js
@ -33,29 +33,10 @@ function Daemon(options) {
|
|||||||
self[key] = exports[key];
|
self[key] = exports[key];
|
||||||
});
|
});
|
||||||
|
|
||||||
this.on('newListener', function(name) {
|
|
||||||
if (name === 'open') {
|
|
||||||
//self.start();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
util.inherits(Daemon, EventEmitter);
|
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.instances = {};
|
||||||
Daemon.prototype.instances = Daemon.instances;
|
Daemon.prototype.instances = Daemon.instances;
|
||||||
|
|
||||||
@ -71,77 +52,17 @@ Daemon.prototype.start = function(callback) {
|
|||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if (this.instances[this.datadir]) {
|
if (this.instances[this.datadir]) {
|
||||||
return;
|
return callback(new Error('Daemon already started'));
|
||||||
}
|
}
|
||||||
this.instances[this.datadir] = true;
|
this.instances[this.datadir] = true;
|
||||||
|
|
||||||
var none = {};
|
bitcoind.start(this.options, function(err) {
|
||||||
var isSignal = {};
|
if(err) {
|
||||||
var sigint = { name: 'SIGINT', signal: isSignal };
|
return callback(err);
|
||||||
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, status) {
|
|
||||||
self._started = true;
|
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) {
|
bitcoind.onBlocksReady(function(err, result) {
|
||||||
|
|
||||||
function onTipUpdateListener(result) {
|
function onTipUpdateListener(result) {
|
||||||
@ -155,58 +76,18 @@ Daemon.prototype.start = function(callback) {
|
|||||||
|
|
||||||
bitcoind.onTipUpdate(onTipUpdateListener);
|
bitcoind.onTipUpdate(onTipUpdateListener);
|
||||||
|
|
||||||
self.emit('ready', result);
|
|
||||||
|
|
||||||
bitcoind.startTxMon(function(txs) {
|
bitcoind.startTxMon(function(txs) {
|
||||||
for(var i = 0; i < txs.length; i++) {
|
for(var i = 0; i < txs.length; i++) {
|
||||||
self.emit('tx', txs[i]);
|
self.emit('tx', txs[i]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
setImmediate(function() {
|
||||||
|
self.emit('ready', result);
|
||||||
setTimeout(function callee() {
|
|
||||||
if (err) {
|
|
||||||
self.emit('error', err);
|
|
||||||
callback(err);
|
|
||||||
} else {
|
|
||||||
self.emit('open', status);
|
|
||||||
callback();
|
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() {
|
Daemon.prototype.isSynced = function() {
|
||||||
@ -258,33 +139,17 @@ Daemon.prototype.getInfo = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Daemon.prototype.stop = function(callback) {
|
Daemon.prototype.stop = function(callback) {
|
||||||
if (Daemon.stopping) return [];
|
|
||||||
var self = this;
|
var self = this;
|
||||||
return bitcoind.stop(function(err, status) {
|
return bitcoind.stop(function(err, status) {
|
||||||
if (err) {
|
setImmediate(function() {
|
||||||
self.error(err.message);
|
if (err) {
|
||||||
} else {
|
return callback(err);
|
||||||
log.info(status);
|
} else {
|
||||||
}
|
log.info(status);
|
||||||
if (!callback) return;
|
return callback();
|
||||||
return callback(err, status);
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
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;
|
module.exports = Daemon;
|
||||||
|
|||||||
15
lib/node.js
15
lib/node.js
@ -236,12 +236,13 @@ Node.prototype._syncBitcoind = function() {
|
|||||||
|
|
||||||
async.whilst(function() {
|
async.whilst(function() {
|
||||||
height = self.chain.tip.__height;
|
height = self.chain.tip.__height;
|
||||||
return height < self.bitcoindHeight;
|
return height < self.bitcoindHeight && !self.stopping;
|
||||||
}, function(done) {
|
}, function(done) {
|
||||||
self.bitcoind.getBlock(height + 1, function(err, blockBuffer) {
|
self.bitcoind.getBlock(height + 1, function(err, blockBuffer) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
var block = self.Block.fromBuffer(blockBuffer);
|
var block = self.Block.fromBuffer(blockBuffer);
|
||||||
if (block.prevHash === self.chain.tip.hash) {
|
if (block.prevHash === self.chain.tip.hash) {
|
||||||
|
|
||||||
@ -259,17 +260,17 @@ Node.prototype._syncBitcoind = function() {
|
|||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete self.chain.tip.__transactions;
|
delete self.chain.tip.__transactions;
|
||||||
self.chain.tip = block;
|
self.chain.tip = block;
|
||||||
log.debug('Saving metadata');
|
log.debug('Saving metadata');
|
||||||
self.chain.saveMetadata();
|
self.chain.saveMetadata();
|
||||||
log.debug('Chain added block to main chain');
|
log.debug('Chain added block to main chain');
|
||||||
self.chain.emit('addblock', block);
|
self.chain.emit('addblock', block);
|
||||||
done();
|
setImmediate(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// This block doesn't progress the current tip, so we'll attempt
|
// This block doesn't progress the current tip, so we'll attempt
|
||||||
// to rewind the chain to the common ancestor of the block and
|
// to rewind the chain to the common ancestor of the block and
|
||||||
// then we can resume syncing.
|
// then we can resume syncing.
|
||||||
@ -397,10 +398,6 @@ Node.prototype._initialize = function() {
|
|||||||
self.bitcoindHeight = info.blocks;
|
self.bitcoindHeight = info.blocks;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.bitcoind.on('open', function(status) {
|
|
||||||
log.info('Bitcoin Core Daemon Status:', status);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Notify that there is a new tip
|
// Notify that there is a new tip
|
||||||
this.bitcoind.on('tip', function(height) {
|
this.bitcoind.on('tip', function(height) {
|
||||||
var percentage = self.bitcoind.syncPercentage();
|
var percentage = self.bitcoind.syncPercentage();
|
||||||
@ -481,9 +478,13 @@ Node.prototype.start = function(callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Node.prototype.stop = function(callback) {
|
Node.prototype.stop = function(callback) {
|
||||||
|
log.info('Stopping Bitcore Node');
|
||||||
var self = this;
|
var self = this;
|
||||||
var services = this.getServiceOrder().reverse();
|
var services = this.getServiceOrder().reverse();
|
||||||
|
|
||||||
|
this.stopping = true;
|
||||||
|
this.emit('stopping');
|
||||||
|
|
||||||
async.eachSeries(
|
async.eachSeries(
|
||||||
services,
|
services,
|
||||||
function(service, next) {
|
function(service, next) {
|
||||||
|
|||||||
@ -885,30 +885,6 @@ async_stop_node_after(uv_work_t *req) {
|
|||||||
delete 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()
|
* GetBlock()
|
||||||
* bitcoind.getBlock([blockhash,blockheight], callback)
|
* bitcoind.getBlock([blockhash,blockheight], callback)
|
||||||
@ -1650,8 +1626,6 @@ init(Handle<Object> target) {
|
|||||||
NODE_SET_METHOD(target, "onBlocksReady", OnBlocksReady);
|
NODE_SET_METHOD(target, "onBlocksReady", OnBlocksReady);
|
||||||
NODE_SET_METHOD(target, "onTipUpdate", OnTipUpdate);
|
NODE_SET_METHOD(target, "onTipUpdate", OnTipUpdate);
|
||||||
NODE_SET_METHOD(target, "stop", StopBitcoind);
|
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, "getBlock", GetBlock);
|
||||||
NODE_SET_METHOD(target, "getTransaction", GetTransaction);
|
NODE_SET_METHOD(target, "getTransaction", GetTransaction);
|
||||||
NODE_SET_METHOD(target, "getTransactionWithBlockInfo", GetTransactionWithBlockInfo);
|
NODE_SET_METHOD(target, "getTransactionWithBlockInfo", GetTransactionWithBlockInfo);
|
||||||
|
|||||||
@ -20,8 +20,6 @@
|
|||||||
NAN_METHOD(StartBitcoind);
|
NAN_METHOD(StartBitcoind);
|
||||||
NAN_METHOD(OnBlocksReady);
|
NAN_METHOD(OnBlocksReady);
|
||||||
NAN_METHOD(OnTipUpdate);
|
NAN_METHOD(OnTipUpdate);
|
||||||
NAN_METHOD(IsStopping);
|
|
||||||
NAN_METHOD(IsStopped);
|
|
||||||
NAN_METHOD(StopBitcoind);
|
NAN_METHOD(StopBitcoind);
|
||||||
NAN_METHOD(GetBlock);
|
NAN_METHOD(GetBlock);
|
||||||
NAN_METHOD(GetTransaction);
|
NAN_METHOD(GetTransaction);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user