mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-09-18 20:02:13 +02:00
http: Abort with clear error instead of hanging forever
Could happen when connection doesn't complete for some reason. Output early warning to give clue about what's up. Prior check+log message before even starting to wait was a bit too eager to hint at something being wrong.
This commit is contained in:
@@ -197,10 +197,10 @@ public:
|
|||||||
return WITH_LOCK(m_mutex, return m_tracker.size());
|
return WITH_LOCK(m_mutex, return m_tracker.size());
|
||||||
}
|
}
|
||||||
//! Wait until there are no more connections with active requests in the tracker
|
//! Wait until there are no more connections with active requests in the tracker
|
||||||
void WaitUntilEmpty() const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
|
void WaitUntilEmpty(std::chrono::seconds timeout) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
|
||||||
{
|
{
|
||||||
WAIT_LOCK(m_mutex, lock);
|
WAIT_LOCK(m_mutex, lock);
|
||||||
m_cv.wait(lock, [this]() EXCLUSIVE_LOCKS_REQUIRED(m_mutex) { return m_tracker.empty(); });
|
m_cv.wait_for(lock, timeout, [this]() EXCLUSIVE_LOCKS_REQUIRED(m_mutex) { return m_tracker.empty(); });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
//! Track active requests
|
//! Track active requests
|
||||||
@@ -536,11 +536,19 @@ void StopHTTPServer()
|
|||||||
evhttp_del_accept_socket(eventHTTP, socket);
|
evhttp_del_accept_socket(eventHTTP, socket);
|
||||||
}
|
}
|
||||||
boundSockets.clear();
|
boundSockets.clear();
|
||||||
{
|
// Give clients time to close down TCP connections from their side before we
|
||||||
if (const auto n_connections{g_requests.CountActiveConnections()}; n_connections != 0) {
|
// free eventHTTP, this avoids issues like RemoteDisconnected exceptions in
|
||||||
LogDebug(BCLog::HTTP, "Waiting for %d connections to stop HTTP server\n", n_connections);
|
// the test framework.
|
||||||
|
g_requests.WaitUntilEmpty(/*timeout=*/30s);
|
||||||
|
if (auto connections{g_requests.CountActiveConnections()}) {
|
||||||
|
LogWarning("%d remaining HTTP connection(s) after 30s timeout, waiting for longer.", connections);
|
||||||
|
g_requests.WaitUntilEmpty(/*timeout=*/10min);
|
||||||
|
if ((connections = g_requests.CountActiveConnections())) {
|
||||||
|
LogError("%d remaining HTTP connection(s) after long timeout. "
|
||||||
|
"Aborting to avoid potential use-after-frees from "
|
||||||
|
"connections still running after freeing eventHTTP.", connections);
|
||||||
|
std::abort();
|
||||||
}
|
}
|
||||||
g_requests.WaitUntilEmpty();
|
|
||||||
}
|
}
|
||||||
if (eventHTTP) {
|
if (eventHTTP) {
|
||||||
// Schedule a callback to call evhttp_free in the event base thread, as
|
// Schedule a callback to call evhttp_free in the event base thread, as
|
||||||
|
Reference in New Issue
Block a user