From 3aacd0a0898402355d9dae07b84d888af059897c Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Wed, 17 Sep 2014 14:08:26 -0700 Subject: [PATCH] no allocator error on shutdown. --- example/index.js | 7 ----- lib/bitcoind.js | 29 +++++++++++------ src/bitcoindjs.cc | 80 +++++++++++++++++++++-------------------------- src/bitcoindjs.h | 2 +- 4 files changed, 55 insertions(+), 63 deletions(-) diff --git a/example/index.js b/example/index.js index 41032237..fcbb8d2e 100755 --- a/example/index.js +++ b/example/index.js @@ -12,10 +12,3 @@ bitcoind.start(function(err) { console.log('bitcoind: status="%s"', status); }); }); - -process.on('SIGINT', function() { - return bitcoind.stop(function(err) { - if (err) throw err; - return process.exit(0); - }); -}); diff --git a/lib/bitcoind.js b/lib/bitcoind.js index 3b44896e..858aa7dc 100644 --- a/lib/bitcoind.js +++ b/lib/bitcoind.js @@ -35,23 +35,36 @@ Bitcoin.prototype.start = function(callback) { callback(err); callback = null; } + if (err) { self.emit('error', err); } else { 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 // or on node's event loop, so we need to keep node open. - this._interval = setInterval(function() { - if (bitcoindjs.stopped()) { - clearInterval(self._interval); - delete self._interval; + this._shutdown = setInterval(function() { + if (!self._stoppingSaid && bitcoindjs.stopping()) { + self._stoppingSaid = true; + 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 = @@ -76,10 +89,6 @@ Bitcoin.prototype.error = function() { Bitcoin.prototype.stop = Bitcoin.prototype.close = function(callback) { var self = this; - if (this._interval) { - clearInterval(this._interval); - delete this._interval; - } return bitcoindjs.stop(function(err, status) { if (err) { self.error(err.message); diff --git a/src/bitcoindjs.cc b/src/bitcoindjs.cc index ff789c20..4ea72acd 100644 --- a/src/bitcoindjs.cc +++ b/src/bitcoindjs.cc @@ -95,8 +95,6 @@ #define MIN_CORE_FILEDESCRIPTORS 150 -extern volatile bool fRequestShutdown; - using namespace std; using namespace boost; @@ -105,6 +103,7 @@ extern void DetectShutdownThread(boost::thread_group*); extern void StartNode(boost::thread_group&); extern void ThreadScriptCheck(); extern void StartShutdown(); +extern bool ShutdownRequested(); extern bool AppInit2(boost::thread_group&); extern bool AppInit(int, char**); extern bool SoftSetBoolArg(const std::string&, bool); @@ -151,8 +150,8 @@ async_stop_node_after(uv_work_t *req); static int start_node(void); -static int -_start_node(void); +static void +start_node_thread(void); static void open_pipes(int **out_pipe, int **log_pipe); @@ -169,6 +168,8 @@ async_parse_logs_after(uv_work_t *req); extern "C" void init(Handle); +static bool shutdownComplete = false; + /** * async_node_data * Where the uv async request data resides. @@ -213,12 +214,12 @@ NAN_METHOD(StartBitcoind) { // Run in a separate thread. // +#if OUTPUT_REDIR int *out_pipe = (int *)malloc(2 * sizeof(int)); int *log_pipe = (int *)malloc(2 * sizeof(int)); open_pipes(&out_pipe, &log_pipe); -#ifdef OUTPUT_REDIR uv_work_t *req_parse_logs = new uv_work_t(); async_log_data* data_parse_logs = new async_log_data(); data_parse_logs->out_pipe = &out_pipe; @@ -227,9 +228,11 @@ NAN_METHOD(StartBitcoind) { data_parse_logs->result = NULL; data_parse_logs->callback = Persistent::New(callback); req_parse_logs->data = data_parse_logs; + int status_parse_logs = uv_queue_work(uv_default_loop(), req_parse_logs, async_parse_logs, (uv_after_work_cb)async_parse_logs_after); + assert(status_parse_logs == 0); #endif @@ -251,7 +254,11 @@ NAN_METHOD(StartBitcoind) { assert(status_start_node == 0); +#if OUTPUT_REDIR NanReturnValue(NanNew(log_pipe[1])); +#else + NanReturnValue(NanNew(-1)); +#endif } /** @@ -309,57 +316,49 @@ async_start_node_after(uv_work_t *req) { delete req; } +/** + * IsStopping() + * bitcoind.stopping() + */ + +NAN_METHOD(IsStopping) { + NanScope(); + NanReturnValue(NanNew(ShutdownRequested())); +} + /** * IsStopped() * bitcoind.stopped() */ -NAN_METHOD(isStopped) { +NAN_METHOD(IsStopped) { NanScope(); - NanReturnValue(NanNew(fRequestShutdown)); + NanReturnValue(NanNew(shutdownComplete)); } /** * start_node(void) + * start_node_thread(void) * A reimplementation of AppInit2 minus * the logging and argument parsing. */ static int start_node(void) { - // - // main: - // - - // Connect bitcoind signal handlers noui_connect(); - // - // appinit1 / appinit2: - // + (boost::thread *)new boost::thread(boost::bind(&start_node_thread)); - boost::thread* node_thread = NULL; - node_thread = new boost::thread(boost::bind(&_start_node)); - - // - // main: - // - - // if (fRet && fDaemon) { - // return 0; - // } - - // return fRet ? 0 : 1; + // horrible fix for a race condition + sleep(2); + signal(SIGINT, SIG_DFL); + signal(SIGHUP, SIG_DFL); return 0; } -static int -_start_node(void) { - // - // appinit1: - // - +static void +start_node_thread(void) { boost::thread_group threadGroup; boost::thread* detectShutdownThread = NULL; @@ -370,24 +369,15 @@ _start_node(void) { }; ParseParameters(argc, argv); ReadConfigFile(mapArgs, mapMultiArgs); - // Check for -testnet or -regtest parameter (TestNet() calls are only valid after this clause) if (!SelectParamsFromCommandLine()) { - return 1; + return; } // CreatePidFile(GetPidFile(), getpid()); detectShutdownThread = new boost::thread( boost::bind(&DetectShutdownThread, &threadGroup)); - // - // appinit2: - // - int fRet = AppInit2(threadGroup); - // - // appinit1: - // - if (!fRet) { if (detectShutdownThread) detectShutdownThread->interrupt(); @@ -400,8 +390,7 @@ _start_node(void) { detectShutdownThread = NULL; } Shutdown(); - - return fRet ? 0 : 1; + shutdownComplete = true; } /** @@ -656,6 +645,7 @@ init(Handle target) { NanScope(); NODE_SET_METHOD(target, "start", StartBitcoind); NODE_SET_METHOD(target, "stop", StopBitcoind); + NODE_SET_METHOD(target, "stopping", IsStopping); NODE_SET_METHOD(target, "stopped", IsStopped); } diff --git a/src/bitcoindjs.h b/src/bitcoindjs.h index ad9fa75e..b5119157 100644 --- a/src/bitcoindjs.h +++ b/src/bitcoindjs.h @@ -6,4 +6,4 @@ * A bitcoind node.js binding header file. */ -#define PARSE_LOGS_ENABLED 0 +#define OUTPUT_REDIR 0