From 949f77322030976154a108e5b076c45c71737a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 31 Aug 2026 01:02:46 +0200 Subject: [PATCH] WebServer: bail out of an upload whose peer disconnected Same root cause as the websocket spin this branch fixes, different symptom, so it belongs with the InputSink EOF change rather than apart from it. ReadBinaryUntilTerminator() returns 0 both when nothing has arrived yet and when the peer is gone, and the multipart loop only exits on finding its terminator - so a cancelled browser upload left a handler thread spinning forever. That also hangs web server shutdown, since it joins its handler threads. Now that InputSink reports EOF, ask it. (Moved here from misc-correctness-fixes, which will be rebased on top of this.) --- Core/WebServer.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Core/WebServer.cpp b/Core/WebServer.cpp index e2b99c5f35..1d9ad232be 100644 --- a/Core/WebServer.cpp +++ b/Core/WebServer.cpp @@ -651,6 +651,16 @@ static MultiPartResult HandleMultipartPart(const http::ServerRequest &request, s } progress.AddBytes(readBytes); bytesTransferred += readBytes; + if (readBytes == 0 && !terminatorFound && (request.In()->AtEnd() || request.In()->HasError())) { + // Peer went away mid-upload (a cancelled browser upload, say). Without this the loop + // spins forever, which also blocks web server shutdown since it joins its threads. + ERROR_LOG(Log::HTTP, "Connection closed during upload of '%s'", filename.c_str()); + if (fp) { + fclose(fp); + File::Delete(destPath); + } + return MultiPartResult::RequestError; + } if (terminatorFound) { INFO_LOG(Log::HTTP, "Found terminator, skipping and proceeding."); break;