From 726b3663cc8e2164d4e9452f12f5866f5e8f6f1a Mon Sep 17 00:00:00 2001 From: furszy Date: Thu, 12 Feb 2026 14:08:22 -0500 Subject: [PATCH] http: properly respond to HTTP request during shutdown Makes sure we respond to the client as the HTTP request attempts to submit a task to the thread pool during server shutdown. Roughly what happens: 1) The server receives an HTTP request and starts calling http_request_cb(). 2) Meanwhile on another thread, shutdown is triggered which calls InterruptHTTPServer() and unregisters libevent http_request_cb() callback and interrupts the thread pool. 3) The request (step 1) resumes and tries to submit a task to the now-interrupted server. This fix detects failed submissions immediately, and the server responds with HTTP_SERVICE_UNAVAILABLE. --- src/httpserver.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 671e119642f..587f7d21ac8 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -211,7 +211,7 @@ static void http_request_cb(struct evhttp_request* req, void* arg) } } } - auto hreq{std::make_unique(req, *static_cast(arg))}; + auto hreq{std::make_shared(req, *static_cast(arg))}; // Early address-based allow check if (!ClientAllowed(hreq->GetPeer())) { @@ -258,7 +258,7 @@ static void http_request_cb(struct evhttp_request* req, void* arg) return; } - auto item = [req = std::move(hreq), in_path = std::move(path), fn = i->handler]() { + auto item = [req = hreq, in_path = std::move(path), fn = i->handler]() { std::string err_msg; try { fn(req.get(), in_path); @@ -276,7 +276,13 @@ static void http_request_cb(struct evhttp_request* req, void* arg) req->WriteReply(HTTP_INTERNAL_SERVER_ERROR, err_msg); }; - [[maybe_unused]] auto _{g_threadpool_http.Submit(std::move(item))}; + if (auto res = g_threadpool_http.Submit(std::move(item)); !res.has_value()) { + Assume(hreq.use_count() == 1); // ensure request will be deleted + // Both SubmitError::Inactive and SubmitError::Interrupted mean shutdown + LogWarning("HTTP request rejected during server shutdown: '%s'", SubmitErrorString(res.error())); + hreq->WriteReply(HTTP_SERVICE_UNAVAILABLE, "Request rejected during server shutdown"); + return; + } } else { hreq->WriteReply(HTTP_NOT_FOUND); }