1
0
mirror of https://github.com/OpenTTD/OpenTTD.git synced 2025-08-13 01:29:10 +00:00

Fix: libcurl HTTP thread race at uninit preventing thread exit

This commit is contained in:
Jonathan G Rennison
2024-01-04 01:02:22 +00:00
parent 4fcd94a1cb
commit 58ac05202d
2 changed files with 28 additions and 5 deletions

View File

@@ -230,8 +230,10 @@ void HttpThread()
request->callback.OnFailure();
}
/* Wait till the callback tells us all data is dequeued. */
request->callback.WaitTillEmpty();
/* Wait till the callback tells us all data is dequeued, or _http_thread_exit has been set. */
request->callback.WaitTillEmptyOrCondition([]() -> bool {
return _http_thread_exit;
});
}
curl_easy_cleanup(curl);
@@ -278,6 +280,11 @@ void NetworkHTTPUninitialize()
_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);
_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);
while (!queue.empty()) {
while (!(queue.empty() || condition())) {
this->queue_cv.wait(lock);
}
}
@@ -95,6 +97,20 @@ public:
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()