no allocator error on shutdown.

This commit is contained in:
Christopher Jeffrey 2014-09-17 14:08:26 -07:00
parent 7c4b707387
commit 3aacd0a089
4 changed files with 55 additions and 63 deletions

View File

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

View File

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

View File

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

View File

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