http: Ensure eventHTTP is always freed

There is a race between ThreadHTTP exiting and our queuing of the freeing-event (event_base_once).

Additional free was useful in 709 of 962 runs.
This commit is contained in:
Hodlinator
2025-02-21 14:31:36 +01:00
parent 1350087f9a
commit 757de96db5

View File

@@ -546,16 +546,25 @@ void StopHTTPServer()
// Schedule a callback to call evhttp_free in the event base thread, as
// otherwise eventHTTP often keeps internal events alive, meaning
// aforementioned thread would never run out of events and exit.
event_base_once(eventBase, -1, EV_TIMEOUT, [](evutil_socket_t, short, void*) {
if (event_base_once(eventBase, -1, EV_TIMEOUT, [](evutil_socket_t, short, void*) {
evhttp_free(eventHTTP);
eventHTTP = nullptr;
}, nullptr, nullptr);
}, nullptr, nullptr) != 0) {
LogDebug(BCLog::HTTP, "event_base_once failed");
}
}
if (eventBase) {
LogDebug(BCLog::HTTP, "Waiting for HTTP event thread to exit\n");
if (g_thread_http.joinable()) g_thread_http.join();
if (eventHTTP) {
LogDebug(BCLog::HTTP, "Freeing eventHTTP-event was not picked up by ThreadHTTP before it exited.");
evhttp_free(eventHTTP);
eventHTTP = nullptr;
}
event_base_free(eventBase);
eventBase = nullptr;
} else {
Assume(!g_thread_http.joinable());
}
g_work_queue.reset();
LogDebug(BCLog::HTTP, "Stopped HTTP server\n");