mirror of https://github.com/OpenTTD/OpenTTD
Fix: libcurl HTTP thread race at uninit preventing thread exit
parent
c6dafb0865
commit
51ef416b49
|
@ -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();
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue