bitcoind: handle unexpected process exits
This commit is contained in:
parent
d958e83f1d
commit
d28f8567f1
@ -52,6 +52,9 @@ function Bitcoin(options) {
|
||||
this.maxAddressesQuery = options.maxAddressesQuery || Bitcoin.DEFAULT_MAX_ADDRESSES_QUERY;
|
||||
this.shutdownTimeout = options.shutdownTimeout || Bitcoin.DEFAULT_SHUTDOWN_TIMEOUT;
|
||||
|
||||
// spawn restart setting
|
||||
this.spawnRestartTime = options.spawnRestartTime || Bitcoin.DEFAULT_SPAWN_RESTART_TIME;
|
||||
|
||||
// try all interval
|
||||
this.tryAllInterval = options.tryAllInterval || Bitcoin.DEFAULT_TRY_ALL_INTERVAL;
|
||||
this.startRetryInterval = options.startRetryInterval || Bitcoin.DEFAULT_START_RETRY_INTERVAL;
|
||||
@ -70,6 +73,7 @@ Bitcoin.dependencies = [];
|
||||
Bitcoin.DEFAULT_MAX_HISTORY = 10;
|
||||
Bitcoin.DEFAULT_SHUTDOWN_TIMEOUT = 15000;
|
||||
Bitcoin.DEFAULT_MAX_ADDRESSES_QUERY = 10000;
|
||||
Bitcoin.DEFAULT_SPAWN_RESTART_TIME = 5000;
|
||||
Bitcoin.DEFAULT_TRY_ALL_INTERVAL = 1000;
|
||||
Bitcoin.DEFAULT_REINDEX_INTERVAL = 10000;
|
||||
Bitcoin.DEFAULT_START_RETRY_INTERVAL = 5000;
|
||||
@ -613,6 +617,39 @@ Bitcoin.prototype._loadTipFromNode = function(node, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
Bitcoin.prototype._stopSpawnedBitcoin = function(callback) {
|
||||
var spawnOptions = this.options.spawn;
|
||||
var pidPath = spawnOptions.datadir + '/bitcoind.pid';
|
||||
|
||||
function stopProcess() {
|
||||
fs.readFile(pidPath, 'utf8', function(err, pid) {
|
||||
if (err && err.code === 'ENOENT') {
|
||||
// pid file doesn't exist we can continue
|
||||
return callback(null);
|
||||
} else if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
pid = parseInt(pid);
|
||||
log.warn('Stopping existing spawned bitcoin process with pid: ' + pid);
|
||||
try {
|
||||
process.kill(pid, 'SIGINT');
|
||||
} catch(err) {
|
||||
if (err && err.code === 'ESRCH') {
|
||||
log.warn('Unclean bitcoin process shutdown, process not found with pid: ' + pid);
|
||||
return callback(null);
|
||||
} else if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
}
|
||||
setTimeout(function() {
|
||||
stopProcess();
|
||||
}, 10000);
|
||||
});
|
||||
}
|
||||
|
||||
stopProcess();
|
||||
};
|
||||
|
||||
Bitcoin.prototype._spawnChildProcess = function(callback) {
|
||||
var self = this;
|
||||
|
||||
@ -634,43 +671,68 @@ Bitcoin.prototype._spawnChildProcess = function(callback) {
|
||||
if (self._getNetworkOption()) {
|
||||
options.push(self._getNetworkOption());
|
||||
}
|
||||
self.spawn.process = spawn(this.spawn.exec, options, {stdio: 'inherit'});
|
||||
|
||||
self.spawn.process.on('error', function(err) {
|
||||
log.error(err);
|
||||
});
|
||||
|
||||
async.retry({times: 60, interval: self.startRetryInterval}, function(done) {
|
||||
if (self.node.stopping) {
|
||||
return done(new Error('Stopping while trying to connect to bitcoind.'));
|
||||
}
|
||||
|
||||
node.client = new BitcoinRPC({
|
||||
protocol: 'http',
|
||||
host: '127.0.0.1',
|
||||
port: self.spawn.config.rpcport,
|
||||
user: self.spawn.config.rpcuser,
|
||||
pass: self.spawn.config.rpcpassword
|
||||
});
|
||||
|
||||
self._loadTipFromNode(node, done);
|
||||
|
||||
}, function(err) {
|
||||
self._stopSpawnedBitcoin(function(err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
self._initZmqSubSocket(node, self.spawn.config.zmqpubrawtx);
|
||||
log.info('Starting bitcoin process');
|
||||
self.spawn.process = spawn(self.spawn.exec, options, {stdio: 'inherit'});
|
||||
|
||||
self._checkReindex(node, function(err) {
|
||||
self.spawn.process.on('error', function(err) {
|
||||
self.emit('error', err);
|
||||
});
|
||||
|
||||
self.spawn.process.once('exit', function(code) {
|
||||
if (!self.node.stopping) {
|
||||
log.warn('Bitcoin process unexpectedly exited with code:', code);
|
||||
log.warn('Restarting bitcoin child process in ' + self.spawnRestartTime + 'ms');
|
||||
setTimeout(function() {
|
||||
self._spawnChildProcess(function(err) {
|
||||
if (err) {
|
||||
return self.emit('error', err);
|
||||
}
|
||||
log.warn('Bitcoin process restarted');
|
||||
});
|
||||
}, self.spawnRestartTime);
|
||||
}
|
||||
});
|
||||
|
||||
async.retry({times: 60, interval: self.startRetryInterval}, function(done) {
|
||||
if (self.node.stopping) {
|
||||
return done(new Error('Stopping while trying to connect to bitcoind.'));
|
||||
}
|
||||
|
||||
node.client = new BitcoinRPC({
|
||||
protocol: 'http',
|
||||
host: '127.0.0.1',
|
||||
port: self.spawn.config.rpcport,
|
||||
user: self.spawn.config.rpcuser,
|
||||
pass: self.spawn.config.rpcpassword
|
||||
});
|
||||
|
||||
self._loadTipFromNode(node, done);
|
||||
|
||||
}, function(err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
self._checkSyncedAndSubscribeZmqEvents(node);
|
||||
callback(null, node);
|
||||
|
||||
self._initZmqSubSocket(node, self.spawn.config.zmqpubrawtx);
|
||||
|
||||
self._checkReindex(node, function(err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
self._checkSyncedAndSubscribeZmqEvents(node);
|
||||
callback(null, node);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
Bitcoin.prototype._connectProcess = function(config, callback) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user