diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/httpserver.cpp | 32 | ||||
-rw-r--r-- | src/rpc/client.cpp | 1 | ||||
-rw-r--r-- | src/rpc/server.cpp | 8 |
3 files changed, 19 insertions, 22 deletions
diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 00434169cd..cb8578927a 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -10,6 +10,7 @@ #include <util/strencodings.h> #include <netbase.h> #include <rpc/protocol.h> // For HTTP status codes +#include <shutdown.h> #include <sync.h> #include <ui_interface.h> @@ -21,7 +22,6 @@ #include <sys/types.h> #include <sys/stat.h> #include <signal.h> -#include <future> #include <event2/thread.h> #include <event2/buffer.h> @@ -421,7 +421,6 @@ bool UpdateHTTPServerLogging(bool enable) { } std::thread threadHTTP; -std::future<bool> threadResult; static std::vector<std::thread> g_thread_http_workers; void StartHTTPServer() @@ -429,9 +428,7 @@ void StartHTTPServer() LogPrint(BCLog::HTTP, "Starting HTTP server\n"); int rpcThreads = std::max((long)gArgs.GetArg("-rpcthreads", DEFAULT_HTTP_THREADS), 1L); LogPrintf("HTTP: starting %d worker threads\n", rpcThreads); - std::packaged_task<bool(event_base*)> task(ThreadHTTP); - threadResult = task.get_future(); - threadHTTP = std::thread(std::move(task), eventBase); + threadHTTP = std::thread(ThreadHTTP, eventBase); for (int i = 0; i < rpcThreads; i++) { g_thread_http_workers.emplace_back(HTTPWorkQueueRun, workQueue); @@ -442,10 +439,6 @@ void InterruptHTTPServer() { LogPrint(BCLog::HTTP, "Interrupting HTTP server\n"); if (eventHTTP) { - // Unlisten sockets - for (evhttp_bound_socket *socket : boundSockets) { - evhttp_del_accept_socket(eventHTTP, socket); - } // Reject requests on current connections evhttp_set_gencb(eventHTTP, http_reject_request_cb, nullptr); } @@ -465,20 +458,14 @@ void StopHTTPServer() delete workQueue; workQueue = nullptr; } + // Unlisten sockets, these are what make the event loop running, which means + // that after this and all connections are closed the event loop will quit. + for (evhttp_bound_socket *socket : boundSockets) { + evhttp_del_accept_socket(eventHTTP, socket); + } + boundSockets.clear(); if (eventBase) { LogPrint(BCLog::HTTP, "Waiting for HTTP event thread to exit\n"); - // Exit the event loop as soon as there are no active events. - event_base_loopexit(eventBase, nullptr); - // Give event loop a few seconds to exit (to send back last RPC responses), then break it - // Before this was solved with event_base_loopexit, but that didn't work as expected in - // at least libevent 2.0.21 and always introduced a delay. In libevent - // master that appears to be solved, so in the future that solution - // could be used again (if desirable). - // (see discussion in https://github.com/bitcoin/bitcoin/pull/6990) - if (threadResult.valid() && threadResult.wait_for(std::chrono::milliseconds(2000)) == std::future_status::timeout) { - LogPrintf("HTTP event loop did not exit within allotted time, sending loopbreak\n"); - event_base_loopbreak(eventBase); - } threadHTTP.join(); } if (eventHTTP) { @@ -583,6 +570,9 @@ void HTTPRequest::WriteHeader(const std::string& hdr, const std::string& value) void HTTPRequest::WriteReply(int nStatus, const std::string& strReply) { assert(!replySent && req); + if (ShutdownRequested()) { + WriteHeader("Connection", "close"); + } // Send event to main http thread to send reply message struct evbuffer* evb = evhttp_request_get_output_buffer(req); assert(evb); diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 2b99808c07..6f1bfb03d1 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -162,6 +162,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "rescanblockchain", 1, "stop_height"}, { "createwallet", 1, "disable_private_keys"}, { "getnodeaddresses", 0, "count"}, + { "stop", 0, "wait" }, }; // clang-format on diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 97745c62d6..dc81a9a861 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -221,6 +221,9 @@ UniValue help(const JSONRPCRequest& jsonRequest) UniValue stop(const JSONRPCRequest& jsonRequest) { // Accept the deprecated and ignored 'detach' boolean argument + // Also accept the hidden 'wait' integer argument (milliseconds) + // For instance, 'stop 1000' makes the call wait 1 second before returning + // to the client (intended for testing) if (jsonRequest.fHelp || jsonRequest.params.size() > 1) throw std::runtime_error( RPCHelpMan{"stop", @@ -229,6 +232,9 @@ UniValue stop(const JSONRPCRequest& jsonRequest) // Event loop will exit after current HTTP requests have been handled, so // this reply will get back to the client. StartShutdown(); + if (jsonRequest.params[0].isNum()) { + MilliSleep(jsonRequest.params[0].get_int()); + } return "Bitcoin server stopping"; } @@ -255,7 +261,7 @@ static const CRPCCommand vRPCCommands[] = // --------------------- ------------------------ ----------------------- ---------- /* Overall control/query calls */ { "control", "help", &help, {"command"} }, - { "control", "stop", &stop, {} }, + { "control", "stop", &stop, {"wait"} }, { "control", "uptime", &uptime, {} }, }; // clang-format on |