From 1bb1c66b1548cbad52cc107b40f24a330edca2e1 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Wed, 26 Feb 2020 00:00:07 +0100 Subject: [PATCH] Fix an issue where a Kaeru connected to a nonfunctional input would get lots of sockets in CLOSE_WAIT (and useless threads). It would actually eventually run out of sockets and go entirely zombie if left for too long, which is obviously suboptimal. --- shared/httpd.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/shared/httpd.cpp b/shared/httpd.cpp index 09c0656..74d0c26 100644 --- a/shared/httpd.cpp +++ b/shared/httpd.cpp @@ -45,7 +45,6 @@ void HTTPD::start(int port) port, nullptr, nullptr, &answer_to_connection_thunk, this, - MHD_OPTION_NOTIFY_COMPLETED, nullptr, this, MHD_OPTION_END); if (mhd == nullptr) { fprintf(stderr, "Warning: Could not open HTTP server. (Port already in use?)\n"); @@ -209,10 +208,23 @@ ssize_t HTTPD::Stream::reader_callback_thunk(void *cls, uint64_t pos, char *buf, ssize_t HTTPD::Stream::reader_callback(uint64_t pos, char *buf, size_t max) { unique_lock lock(buffer_mutex); - has_buffered_data.wait(lock, [this] { return should_quit || !buffered_data.empty(); }); + bool has_data = has_buffered_data.wait_for(lock, std::chrono::seconds(60), [this] { return should_quit || !buffered_data.empty(); }); if (should_quit) { return -1; } + if (!has_data) { + // The wait timed out, so tell microhttpd to clean out the socket; + // it's not unlikely that the client has given up anyway. + // This is seemingly the only way to actually reap sockets if we + // do not get any data; returning 0 does nothing, and + // MHD_OPTION_NOTIFY_CONNECTION does not trigger for these cases. + // If not, an instance that has no data to send (typically an instance + // of kaeru connected to a nonfunctional backend) would get a steadily + // increasing amount of sockets in CLOSE_WAIT (ie., the other end has + // hung up, but we haven't called close() yet, as our thread is stuck + // in this callback). + return -1; + } ssize_t ret = 0; while (max > 0 && !buffered_data.empty()) { -- 2.39.2