]> git.sesse.net Git - nageru/commitdiff
Fix an issue where a Kaeru connected to a nonfunctional input would get lots of socke...
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Tue, 25 Feb 2020 23:00:07 +0000 (00:00 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Tue, 25 Feb 2020 23:43:59 +0000 (00:43 +0100)
It would actually eventually run out of sockets and go entirely zombie
if left for too long, which is obviously suboptimal.

shared/httpd.cpp

index 09c065693f005dbcd137b95f1ade099f387a27e5..74d0c26d72b1252ae1485490ab2daef41725211c 100644 (file)
@@ -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<mutex> 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()) {