aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2018-02-08 08:53:40 +0100
committerWladimir J. van der Laan <laanwj@gmail.com>2018-02-08 09:21:49 +0100
commit6db4fa7ad32985cf85c903966be69972bcb6b1d0 (patch)
tree8956e18e8799233882ba31a01ad5c3358a3e6a3a /src
parent11f3eac793348ee8e578838926c6dbae772cb8e5 (diff)
parent11e01515fe0fbc7823d4111ad6e016a02c485a78 (diff)
Merge #12366: http: Join worker threads before deleting work queue
11e0151 http: Remove numThreads and ThreadCounter (Wladimir J. van der Laan) f946654 http: Remove WaitExit from WorkQueue (Wladimir J. van der Laan) b1c2370 http: Join worker threads before deleting work queue (Wladimir J. van der Laan) Pull request description: This prevents a potential race condition if control flow ends up in `ShutdownHTTPServer` before the thread gets to `queue->Run()`, deleting the work queue while workers are still going to use it. Meant to fix #12362. Tree-SHA512: 8108514aeee5b2067a3736ed028014b580d1cbf8530ac7682b8a23070133dfa1ca21db4358c9158ea57e8811e0551395b6cb769887876b9cfce067ee968d0642
Diffstat (limited to 'src')
-rw-r--r--src/httpserver.cpp42
1 files changed, 8 insertions, 34 deletions
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index 73dce8d571..36db530c82 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -73,34 +73,13 @@ private:
std::deque<std::unique_ptr<WorkItem>> queue;
bool running;
size_t maxDepth;
- int numThreads;
-
- /** RAII object to keep track of number of running worker threads */
- class ThreadCounter
- {
- public:
- WorkQueue &wq;
- explicit ThreadCounter(WorkQueue &w): wq(w)
- {
- std::lock_guard<std::mutex> lock(wq.cs);
- wq.numThreads += 1;
- }
- ~ThreadCounter()
- {
- std::lock_guard<std::mutex> lock(wq.cs);
- wq.numThreads -= 1;
- wq.cond.notify_all();
- }
- };
public:
explicit WorkQueue(size_t _maxDepth) : running(true),
- maxDepth(_maxDepth),
- numThreads(0)
+ maxDepth(_maxDepth)
{
}
- /** Precondition: worker threads have all stopped
- * (call WaitExit)
+ /** Precondition: worker threads have all stopped (they have been joined).
*/
~WorkQueue()
{
@@ -119,7 +98,6 @@ public:
/** Thread function */
void Run()
{
- ThreadCounter count(*this);
while (true) {
std::unique_ptr<WorkItem> i;
{
@@ -141,13 +119,6 @@ public:
running = false;
cond.notify_all();
}
- /** Wait for worker threads to exit */
- void WaitExit()
- {
- std::unique_lock<std::mutex> lock(cs);
- while (numThreads > 0)
- cond.wait(lock);
- }
};
struct HTTPPathHandler
@@ -449,6 +420,7 @@ bool UpdateHTTPServerLogging(bool enable) {
std::thread threadHTTP;
std::future<bool> threadResult;
+static std::vector<std::thread> g_thread_http_workers;
bool StartHTTPServer()
{
@@ -460,8 +432,7 @@ bool StartHTTPServer()
threadHTTP = std::thread(std::move(task), eventBase, eventHTTP);
for (int i = 0; i < rpcThreads; i++) {
- std::thread rpc_worker(HTTPWorkQueueRun, workQueue);
- rpc_worker.detach();
+ g_thread_http_workers.emplace_back(HTTPWorkQueueRun, workQueue);
}
return true;
}
@@ -486,7 +457,10 @@ void StopHTTPServer()
LogPrint(BCLog::HTTP, "Stopping HTTP server\n");
if (workQueue) {
LogPrint(BCLog::HTTP, "Waiting for HTTP worker threads to exit\n");
- workQueue->WaitExit();
+ for (auto& thread: g_thread_http_workers) {
+ thread.join();
+ }
+ g_thread_http_workers.clear();
delete workQueue;
workQueue = nullptr;
}