Merge pull request #222 from kleetus/ctrl-c++

Ctrl c++
This commit is contained in:
Braydon Fuller 2015-09-15 10:19:18 -04:00
commit 562fa84344
2 changed files with 96 additions and 21 deletions

View File

@ -9,6 +9,7 @@ var $ = bitcore.util.preconditions;
var log = index.log;
var child_process = require('child_process');
var fs = require('fs');
var shuttingDown = false;
log.debug = function() {};
@ -138,30 +139,41 @@ function cleanShutdown(_process, node) {
* @param {Node} node
*/
function registerExitHandlers(_process, node) {
function exitHandler(options, err) {
if (err) {
log.error('uncaught exception:', err);
if(err.stack) {
log.error(err.stack);
}
node.stop(function(err) {
if(err) {
log.error('Failed to stop services: ' + err);
}
_process.exit(-1);
});
}
if (options.sigint) {
cleanShutdown(_process, node);
}
}
//catches uncaught exceptions
_process.on('uncaughtException', exitHandler.bind(null, {exit:true}));
_process.on('uncaughtException', exitHandler.bind(null, {exit:true}, _process, node));
//catches ctrl+c event
_process.on('SIGINT', exitHandler.bind(null, {sigint:true}));
_process.on('SIGINT', exitHandler.bind(null, {sigint:true}, _process, node));
}
/**
* Will handle all the shutdown tasks that need to take place to ensure a safe exit
* @param {Object} options
* @param {String} options.sigint - The signal given was a SIGINT
* @param {Array} options.exit - The signal given was an uncaughtException
* @param {Object} _process - The Node.js process
* @param {Node} node
* @param {Error} error
*/
function exitHandler(options, _process, node, err) {
if (err) {
log.error('uncaught exception:', err);
if(err.stack) {
log.error(err.stack);
}
node.stop(function(err) {
if(err) {
log.error('Failed to stop services: ' + err);
}
_process.exit(-1);
});
}
if (options.sigint) {
if (!shuttingDown) {
shuttingDown = true;
start.cleanShutdown(_process, node);
}
}
}
/**
@ -254,6 +266,7 @@ function spawnChildProcess(datadir, _process) {
module.exports = start;
module.exports.registerExitHandlers = registerExitHandlers;
module.exports.exitHandler = exitHandler;
module.exports.registerSyncHandlers = registerSyncHandlers;
module.exports.setupServices = setupServices;
module.exports.spawnChildProcess = spawnChildProcess;

View File

@ -304,12 +304,74 @@ describe('#start', function() {
});
it('call spawnChildProcess if there is a config option to do so', function() {
start(options);
registerSync.callCount.should.equal(1);
registerExit.callCount.should.equal(1);
spawn.callCount.should.equal(1);
});
it('not call spawnChildProcess if there is not an option to do so', function() {
options.config.daemon = false;
start(options);
registerSync.callCount.should.equal(1);
registerExit.callCount.should.equal(1);
spawn.callCount.should.equal(0);
});
});
describe('#registerExitHandlers', function() {
var stub;
var registerExitHandlers = require('../../lib/scaffold/start').registerExitHandlers;
before(function() {
stub = sinon.stub(process, 'on');
});
after(function() {
stub.restore();
});
it('should setup two listeners on process when registering exit handlers', function() {
registerExitHandlers(process, {});
stub.callCount.should.equal(2);
});
describe('#exitHandler', function() {
var sandbox;
var cleanShutdown;
var exitHandler;
var logStub;
before(function() {
sandbox = sinon.sandbox.create();
var start = require('../../lib/scaffold/start');
var log = require('../../lib').log;
logStub = sandbox.stub(log, 'error');
cleanShutdown = sandbox.stub(start, 'cleanShutdown', function() {});
exitHandler = require('../../lib/scaffold/start').exitHandler;
});
after(function() {
sandbox.restore();
});
it('should replace the listener for SIGINT after the first SIGINT is handled', function() {
var options = { sigint: true };
var node = {};
exitHandler(options, process, node);
cleanShutdown.callCount.should.equal(1);
exitHandler(options, process, node);
cleanShutdown.callCount.should.equal(1);
});
it('should log all errors and stops the services nonetheless', function() {
var options = { sigint: true };
var stop = sinon.stub();
var node = {
stop: stop
};
exitHandler(options, process, node, new Error('some error'));
logStub.callCount.should.equal(2);
stop.callCount.should.equal(1);
});
});
});
});