Skip to content

Commit

Permalink
http: add evhttp_connection_set_closecb to avoid g_requests hang
Browse files Browse the repository at this point in the history
Prior to this patch, it was possible that if an RPC was interrupted
before the reply was received, the success callback
evhttp_request_set_on_complete_cb would never be called and
g_requests wouldn't be cleaned up. When attempting to shutdown
bitcoind, it would hang waiting for g_requests.empty().

Co-authored-by: Fabian Jahr <fjahr@protonmail.com>
  • Loading branch information
2 people authored and Crypt-iQ committed Jun 23, 2023
1 parent f0758d8 commit 710985d
Showing 1 changed file with 14 additions and 0 deletions.
14 changes: 14 additions & 0 deletions src/httpserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,20 @@ static void http_request_cb(struct evhttp_request* req, void* arg)
{
WITH_LOCK(g_requests_mutex, g_requests.insert(req));
g_requests_cv.notify_all();

auto conn = evhttp_request_get_connection(req);

// Close callback to clear active but running request. This is also
// called if the connection is closed after a successful request, but
// complete callback set below already cleared the state.
evhttp_connection_set_closecb(conn, [](evhttp_connection* conn, void* arg) {
auto req = static_cast<evhttp_request*>(arg);
LOCK(g_requests_mutex);
auto n{g_requests.erase(req)};
if (n == 1 && g_requests.empty()) g_requests_cv.notify_all();
}, req);

// Clear state after successful request.
evhttp_request_set_on_complete_cb(req, [](struct evhttp_request* req, void*) {
auto n{WITH_LOCK(g_requests_mutex, return g_requests.erase(req))};
assert(n == 1);
Expand Down

0 comments on commit 710985d

Please sign in to comment.