no allocator error on shutdown.
This commit is contained in:
parent
7c4b707387
commit
3aacd0a089
@ -12,10 +12,3 @@ bitcoind.start(function(err) {
|
|||||||
console.log('bitcoind: status="%s"', status);
|
console.log('bitcoind: status="%s"', status);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on('SIGINT', function() {
|
|
||||||
return bitcoind.stop(function(err) {
|
|
||||||
if (err) throw err;
|
|
||||||
return process.exit(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@ -35,23 +35,36 @@ Bitcoin.prototype.start = function(callback) {
|
|||||||
callback(err);
|
callback(err);
|
||||||
callback = null;
|
callback = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
self.emit('error', err);
|
self.emit('error', err);
|
||||||
} else {
|
} else {
|
||||||
self.emit('open', status);
|
self.emit('open', status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function stop() {
|
||||||
|
return self.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
process.on('SIGINT', stop);
|
||||||
|
process.on('SIGHUP', stop);
|
||||||
});
|
});
|
||||||
|
|
||||||
// bitcoind's boost threads aren't in the thread pool
|
// bitcoind's boost threads aren't in the thread pool
|
||||||
// or on node's event loop, so we need to keep node open.
|
// or on node's event loop, so we need to keep node open.
|
||||||
this._interval = setInterval(function() {
|
this._shutdown = setInterval(function() {
|
||||||
if (bitcoindjs.stopped()) {
|
if (!self._stoppingSaid && bitcoindjs.stopping()) {
|
||||||
clearInterval(self._interval);
|
self._stoppingSaid = true;
|
||||||
delete self._interval;
|
self.log('shutting down...');
|
||||||
}
|
}
|
||||||
}, 10000);
|
if (bitcoindjs.stopped()) {
|
||||||
|
self.log('shut down.');
|
||||||
|
clearInterval(self._shutdown);
|
||||||
|
delete self._shutdown;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
return this.log('log pipe opened: %d', this.log_pipe);
|
this.log('log pipe opened: %d', this.log_pipe);
|
||||||
};
|
};
|
||||||
|
|
||||||
Bitcoin.prototype.log =
|
Bitcoin.prototype.log =
|
||||||
@ -76,10 +89,6 @@ Bitcoin.prototype.error = function() {
|
|||||||
Bitcoin.prototype.stop =
|
Bitcoin.prototype.stop =
|
||||||
Bitcoin.prototype.close = function(callback) {
|
Bitcoin.prototype.close = function(callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
if (this._interval) {
|
|
||||||
clearInterval(this._interval);
|
|
||||||
delete this._interval;
|
|
||||||
}
|
|
||||||
return bitcoindjs.stop(function(err, status) {
|
return bitcoindjs.stop(function(err, status) {
|
||||||
if (err) {
|
if (err) {
|
||||||
self.error(err.message);
|
self.error(err.message);
|
||||||
|
|||||||
@ -95,8 +95,6 @@
|
|||||||
|
|
||||||
#define MIN_CORE_FILEDESCRIPTORS 150
|
#define MIN_CORE_FILEDESCRIPTORS 150
|
||||||
|
|
||||||
extern volatile bool fRequestShutdown;
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
|
|
||||||
@ -105,6 +103,7 @@ extern void DetectShutdownThread(boost::thread_group*);
|
|||||||
extern void StartNode(boost::thread_group&);
|
extern void StartNode(boost::thread_group&);
|
||||||
extern void ThreadScriptCheck();
|
extern void ThreadScriptCheck();
|
||||||
extern void StartShutdown();
|
extern void StartShutdown();
|
||||||
|
extern bool ShutdownRequested();
|
||||||
extern bool AppInit2(boost::thread_group&);
|
extern bool AppInit2(boost::thread_group&);
|
||||||
extern bool AppInit(int, char**);
|
extern bool AppInit(int, char**);
|
||||||
extern bool SoftSetBoolArg(const std::string&, bool);
|
extern bool SoftSetBoolArg(const std::string&, bool);
|
||||||
@ -151,8 +150,8 @@ async_stop_node_after(uv_work_t *req);
|
|||||||
static int
|
static int
|
||||||
start_node(void);
|
start_node(void);
|
||||||
|
|
||||||
static int
|
static void
|
||||||
_start_node(void);
|
start_node_thread(void);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
open_pipes(int **out_pipe, int **log_pipe);
|
open_pipes(int **out_pipe, int **log_pipe);
|
||||||
@ -169,6 +168,8 @@ async_parse_logs_after(uv_work_t *req);
|
|||||||
extern "C" void
|
extern "C" void
|
||||||
init(Handle<Object>);
|
init(Handle<Object>);
|
||||||
|
|
||||||
|
static bool shutdownComplete = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* async_node_data
|
* async_node_data
|
||||||
* Where the uv async request data resides.
|
* Where the uv async request data resides.
|
||||||
@ -213,12 +214,12 @@ NAN_METHOD(StartBitcoind) {
|
|||||||
// Run in a separate thread.
|
// Run in a separate thread.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#if OUTPUT_REDIR
|
||||||
int *out_pipe = (int *)malloc(2 * sizeof(int));
|
int *out_pipe = (int *)malloc(2 * sizeof(int));
|
||||||
int *log_pipe = (int *)malloc(2 * sizeof(int));
|
int *log_pipe = (int *)malloc(2 * sizeof(int));
|
||||||
|
|
||||||
open_pipes(&out_pipe, &log_pipe);
|
open_pipes(&out_pipe, &log_pipe);
|
||||||
|
|
||||||
#ifdef OUTPUT_REDIR
|
|
||||||
uv_work_t *req_parse_logs = new uv_work_t();
|
uv_work_t *req_parse_logs = new uv_work_t();
|
||||||
async_log_data* data_parse_logs = new async_log_data();
|
async_log_data* data_parse_logs = new async_log_data();
|
||||||
data_parse_logs->out_pipe = &out_pipe;
|
data_parse_logs->out_pipe = &out_pipe;
|
||||||
@ -227,9 +228,11 @@ NAN_METHOD(StartBitcoind) {
|
|||||||
data_parse_logs->result = NULL;
|
data_parse_logs->result = NULL;
|
||||||
data_parse_logs->callback = Persistent<Function>::New(callback);
|
data_parse_logs->callback = Persistent<Function>::New(callback);
|
||||||
req_parse_logs->data = data_parse_logs;
|
req_parse_logs->data = data_parse_logs;
|
||||||
|
|
||||||
int status_parse_logs = uv_queue_work(uv_default_loop(),
|
int status_parse_logs = uv_queue_work(uv_default_loop(),
|
||||||
req_parse_logs, async_parse_logs,
|
req_parse_logs, async_parse_logs,
|
||||||
(uv_after_work_cb)async_parse_logs_after);
|
(uv_after_work_cb)async_parse_logs_after);
|
||||||
|
|
||||||
assert(status_parse_logs == 0);
|
assert(status_parse_logs == 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -251,7 +254,11 @@ NAN_METHOD(StartBitcoind) {
|
|||||||
|
|
||||||
assert(status_start_node == 0);
|
assert(status_start_node == 0);
|
||||||
|
|
||||||
|
#if OUTPUT_REDIR
|
||||||
NanReturnValue(NanNew<Number>(log_pipe[1]));
|
NanReturnValue(NanNew<Number>(log_pipe[1]));
|
||||||
|
#else
|
||||||
|
NanReturnValue(NanNew<Number>(-1));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -309,57 +316,49 @@ async_start_node_after(uv_work_t *req) {
|
|||||||
delete req;
|
delete req;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStopping()
|
||||||
|
* bitcoind.stopping()
|
||||||
|
*/
|
||||||
|
|
||||||
|
NAN_METHOD(IsStopping) {
|
||||||
|
NanScope();
|
||||||
|
NanReturnValue(NanNew<Boolean>(ShutdownRequested()));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IsStopped()
|
* IsStopped()
|
||||||
* bitcoind.stopped()
|
* bitcoind.stopped()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NAN_METHOD(isStopped) {
|
NAN_METHOD(IsStopped) {
|
||||||
NanScope();
|
NanScope();
|
||||||
NanReturnValue(NanNew<Boolean>(fRequestShutdown));
|
NanReturnValue(NanNew<Boolean>(shutdownComplete));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* start_node(void)
|
* start_node(void)
|
||||||
|
* start_node_thread(void)
|
||||||
* A reimplementation of AppInit2 minus
|
* A reimplementation of AppInit2 minus
|
||||||
* the logging and argument parsing.
|
* the logging and argument parsing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
start_node(void) {
|
start_node(void) {
|
||||||
//
|
|
||||||
// main:
|
|
||||||
//
|
|
||||||
|
|
||||||
// Connect bitcoind signal handlers
|
|
||||||
noui_connect();
|
noui_connect();
|
||||||
|
|
||||||
//
|
(boost::thread *)new boost::thread(boost::bind(&start_node_thread));
|
||||||
// appinit1 / appinit2:
|
|
||||||
//
|
|
||||||
|
|
||||||
boost::thread* node_thread = NULL;
|
// horrible fix for a race condition
|
||||||
node_thread = new boost::thread(boost::bind(&_start_node));
|
sleep(2);
|
||||||
|
signal(SIGINT, SIG_DFL);
|
||||||
//
|
signal(SIGHUP, SIG_DFL);
|
||||||
// main:
|
|
||||||
//
|
|
||||||
|
|
||||||
// if (fRet && fDaemon) {
|
|
||||||
// return 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return fRet ? 0 : 1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
_start_node(void) {
|
start_node_thread(void) {
|
||||||
//
|
|
||||||
// appinit1:
|
|
||||||
//
|
|
||||||
|
|
||||||
boost::thread_group threadGroup;
|
boost::thread_group threadGroup;
|
||||||
boost::thread* detectShutdownThread = NULL;
|
boost::thread* detectShutdownThread = NULL;
|
||||||
|
|
||||||
@ -370,24 +369,15 @@ _start_node(void) {
|
|||||||
};
|
};
|
||||||
ParseParameters(argc, argv);
|
ParseParameters(argc, argv);
|
||||||
ReadConfigFile(mapArgs, mapMultiArgs);
|
ReadConfigFile(mapArgs, mapMultiArgs);
|
||||||
// Check for -testnet or -regtest parameter (TestNet() calls are only valid after this clause)
|
|
||||||
if (!SelectParamsFromCommandLine()) {
|
if (!SelectParamsFromCommandLine()) {
|
||||||
return 1;
|
return;
|
||||||
}
|
}
|
||||||
// CreatePidFile(GetPidFile(), getpid());
|
// CreatePidFile(GetPidFile(), getpid());
|
||||||
detectShutdownThread = new boost::thread(
|
detectShutdownThread = new boost::thread(
|
||||||
boost::bind(&DetectShutdownThread, &threadGroup));
|
boost::bind(&DetectShutdownThread, &threadGroup));
|
||||||
|
|
||||||
//
|
|
||||||
// appinit2:
|
|
||||||
//
|
|
||||||
|
|
||||||
int fRet = AppInit2(threadGroup);
|
int fRet = AppInit2(threadGroup);
|
||||||
|
|
||||||
//
|
|
||||||
// appinit1:
|
|
||||||
//
|
|
||||||
|
|
||||||
if (!fRet) {
|
if (!fRet) {
|
||||||
if (detectShutdownThread)
|
if (detectShutdownThread)
|
||||||
detectShutdownThread->interrupt();
|
detectShutdownThread->interrupt();
|
||||||
@ -400,8 +390,7 @@ _start_node(void) {
|
|||||||
detectShutdownThread = NULL;
|
detectShutdownThread = NULL;
|
||||||
}
|
}
|
||||||
Shutdown();
|
Shutdown();
|
||||||
|
shutdownComplete = true;
|
||||||
return fRet ? 0 : 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -656,6 +645,7 @@ init(Handle<Object> target) {
|
|||||||
NanScope();
|
NanScope();
|
||||||
NODE_SET_METHOD(target, "start", StartBitcoind);
|
NODE_SET_METHOD(target, "start", StartBitcoind);
|
||||||
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, "stopped", IsStopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,4 +6,4 @@
|
|||||||
* A bitcoind node.js binding header file.
|
* A bitcoind node.js binding header file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PARSE_LOGS_ENABLED 0
|
#define OUTPUT_REDIR 0
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user