1
0
Fork 0

Fix: libcurl HTTP thread race at uninit preventing thread exit

pull/11684/head
Jonathan G Rennison 2024-01-04 01:02:22 +00:00 committed by Patric Stout
parent c6dafb0865
commit 51ef416b49
2 changed files with 28 additions and 5 deletions

View File

@ -230,8 +230,10 @@ void HttpThread()
request->callback.OnFailure(); request->callback.OnFailure();
} }
/* Wait till the callback tells us all data is dequeued. */ /* Wait till the callback tells us all data is dequeued, or _http_thread_exit has been set. */
request->callback.WaitTillEmpty(); request->callback.WaitTillEmptyOrCondition([]() -> bool {
return _http_thread_exit;
});
} }
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
@ -278,6 +280,11 @@ void NetworkHTTPUninitialize()
_http_thread_exit = true; _http_thread_exit = true;
/* Queues must be cleared (and the queue CV signalled) after _http_thread_exit is set to ensure that the HTTP thread can exit */
for (auto &callback : _http_callbacks) {
callback->ClearQueue();
}
{ {
std::lock_guard<std::mutex> lock(_http_mutex); std::lock_guard<std::mutex> lock(_http_mutex);
_http_cv.notify_one(); _http_cv.notify_one();

View File

@ -75,13 +75,15 @@ public:
} }
/** /**
* Wait till the queue is dequeued. * Wait till the queue is dequeued, or a condition is met.
* @param condition Condition functor.
*/ */
void WaitTillEmpty() template <typename T>
void WaitTillEmptyOrCondition(T condition)
{ {
std::unique_lock<std::mutex> lock(this->mutex); std::unique_lock<std::mutex> lock(this->mutex);
while (!queue.empty()) { while (!(queue.empty() || condition())) {
this->queue_cv.wait(lock); this->queue_cv.wait(lock);
} }
} }
@ -95,6 +97,20 @@ public:
return this->queue.empty(); return this->queue.empty();
} }
/**
* Clear everything in the queue.
*
* Should be called from the Game Thread.
*/
void ClearQueue()
{
std::lock_guard<std::mutex> lock(this->mutex);
this->queue.clear();
this->queue_cv.notify_all();
}
HTTPThreadSafeCallback(HTTPCallback *callback) : callback(callback) {} HTTPThreadSafeCallback(HTTPCallback *callback) : callback(callback) {}
~HTTPThreadSafeCallback() ~HTTPThreadSafeCallback()