From fc365cc3a682fe62639ffa364b93aca5cfc3cf18 Mon Sep 17 00:00:00 2001 From: Mitch Bradley Date: Fri, 9 Oct 2026 11:37:28 -1000 Subject: [PATCH] Don't spend an in-flight credit when nothing was sent With ASYNCWEBSERVER_USE_CHUNK_INFLIGHT, write_send_buffs() took an in-flight credit on every call that reached the content stage, even when the source had no data yet (RESPONSE_TRY_AGAIN) and nothing was written. Credits come back only with acks of sent data, never from polls, so a response whose source is empty on two such calls runs out of credits. From then on every call is ignored and the response stalls for good. Take a credit only when data was actually put in flight. Co-Authored-By: Claude Opus 5.5 --- src/WebResponses.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/WebResponses.cpp b/src/WebResponses.cpp index e520ea100..83d3b7db8 100644 --- a/src/WebResponses.cpp +++ b/src/WebResponses.cpp @@ -499,8 +499,14 @@ size_t AsyncAbstractResponse::write_send_buffs(AsyncWebServerRequest *request, s request->client()->send(); _writtenLength += payloadlen; #if ASYNCWEBSERVER_USE_CHUNK_INFLIGHT - _in_flight += payloadlen; - --_in_flight_credit; // take a credit + // Take a credit only for data actually put in flight. When the source + // had nothing yet (RESPONSE_TRY_AGAIN), nothing will be acked to return + // the credit, and polls don't return credits, so spending one here would + // stall the response for good once the credits run out. + if (payloadlen) { + _in_flight += payloadlen; + --_in_flight_credit; // take a credit + } #endif if (_send_buffer_len == 0) { // buffer empty, we can release mem, otherwise need to keep it till next run (should not happen under normal conditions)