Skip to content

Commit 6db4fa7

Browse files
committed
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
2 parents 11f3eac + 11e0151 commit 6db4fa7

File tree

1 file changed

+8
-34
lines changed

1 file changed

+8
-34
lines changed

src/httpserver.cpp

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -73,34 +73,13 @@ class WorkQueue
7373
std::deque<std::unique_ptr<WorkItem>> queue;
7474
bool running;
7575
size_t maxDepth;
76-
int numThreads;
77-
78-
/** RAII object to keep track of number of running worker threads */
79-
class ThreadCounter
80-
{
81-
public:
82-
WorkQueue &wq;
83-
explicit ThreadCounter(WorkQueue &w): wq(w)
84-
{
85-
std::lock_guard<std::mutex> lock(wq.cs);
86-
wq.numThreads += 1;
87-
}
88-
~ThreadCounter()
89-
{
90-
std::lock_guard<std::mutex> lock(wq.cs);
91-
wq.numThreads -= 1;
92-
wq.cond.notify_all();
93-
}
94-
};
9576

9677
public:
9778
explicit WorkQueue(size_t _maxDepth) : running(true),
98-
maxDepth(_maxDepth),
99-
numThreads(0)
79+
maxDepth(_maxDepth)
10080
{
10181
}
102-
/** Precondition: worker threads have all stopped
103-
* (call WaitExit)
82+
/** Precondition: worker threads have all stopped (they have been joined).
10483
*/
10584
~WorkQueue()
10685
{
@@ -119,7 +98,6 @@ class WorkQueue
11998
/** Thread function */
12099
void Run()
121100
{
122-
ThreadCounter count(*this);
123101
while (true) {
124102
std::unique_ptr<WorkItem> i;
125103
{
@@ -141,13 +119,6 @@ class WorkQueue
141119
running = false;
142120
cond.notify_all();
143121
}
144-
/** Wait for worker threads to exit */
145-
void WaitExit()
146-
{
147-
std::unique_lock<std::mutex> lock(cs);
148-
while (numThreads > 0)
149-
cond.wait(lock);
150-
}
151122
};
152123

153124
struct HTTPPathHandler
@@ -449,6 +420,7 @@ bool UpdateHTTPServerLogging(bool enable) {
449420

450421
std::thread threadHTTP;
451422
std::future<bool> threadResult;
423+
static std::vector<std::thread> g_thread_http_workers;
452424

453425
bool StartHTTPServer()
454426
{
@@ -460,8 +432,7 @@ bool StartHTTPServer()
460432
threadHTTP = std::thread(std::move(task), eventBase, eventHTTP);
461433

462434
for (int i = 0; i < rpcThreads; i++) {
463-
std::thread rpc_worker(HTTPWorkQueueRun, workQueue);
464-
rpc_worker.detach();
435+
g_thread_http_workers.emplace_back(HTTPWorkQueueRun, workQueue);
465436
}
466437
return true;
467438
}
@@ -486,7 +457,10 @@ void StopHTTPServer()
486457
LogPrint(BCLog::HTTP, "Stopping HTTP server\n");
487458
if (workQueue) {
488459
LogPrint(BCLog::HTTP, "Waiting for HTTP worker threads to exit\n");
489-
workQueue->WaitExit();
460+
for (auto& thread: g_thread_http_workers) {
461+
thread.join();
462+
}
463+
g_thread_http_workers.clear();
490464
delete workQueue;
491465
workQueue = nullptr;
492466
}

0 commit comments

Comments
 (0)