Commit ffc25dda authored by jan.koester's avatar jan.koester
Browse files

test

parent b959d9d3
Loading
Loading
Loading
Loading
+33 −0
Original line number Diff line number Diff line
@@ -713,6 +713,39 @@ void libhttppp::HttpEvent::_dispatchH1Request(HttpRequest &cureq, size_t consume
                    cureq2.slots[0].csock->setNonBlock();
                    netplus::reattachConnection(connOwner);
                });
            if (accepted) return;

            // Pool is already at h1DispatchQueueMax pending tasks -- every worker is presumably
            // busy with something slow (or stuck), and every one of those already-queued
            // requests' sockets is detached (invisible to the idle reaper, un-timed until a
            // worker picks them up). Piling this one up behind them too is exactly the same
            // production incident h2DispatchQueueMax exists to prevent for H2, just relocated
            // to H1: eventually a worker frees up and discovers the peer gave up long ago,
            // starting the local close far too late (LAST_ACK never gets ACKed). Answer 503
            // right here instead, synchronously, without ever calling the possibly-slow
            // RequestEvent -- reclaim the socket from sockBox (submit() never queued the
            // lambda that captured it, so sockBox's refcount dropped back to this scope's own
            // copy, same as _dispatchH2Stream's trBox) and write the response directly.
            cureq.slots[0].csock = std::move(*sockBox);
            cureq.slots[0].csock->setBlock();
            cureq.slots[0].csock->setTimeout(kH1OffloadSocketTimeoutMs);
            try {
                HttpResponse busy;
                busy.setState(HTTP503);
                busy.setContentType("text/plain");
                static const std::string kBusyMsg = "server overloaded, try again shortly";
                busy.send(cureq, kBusyMsg, static_cast<int>(kBusyMsg.size()));
                cureq.flushSendData();
            } catch (...) {
                // Best-effort -- the connection is being closed either way below.
            }
            cureq.slots[0].csock->close();
            // Leave csock null afterward, exactly like detachConnection()'s own post-condition
            // above and the accepted-offload path's WebSocket-handoff case -- IoEventHandler's
            // existing null-csock check right after its RequestEvent(con&,...) call site then
            // safely stops touching this connection instead of trying to flush/re-arm an fd
            // that's already closed.
            cureq.slots[0].csock.reset();
            return;
        }
        // Connection lookup/detach failed (shouldn't happen while we're still holding