From e3a7470c8908fb1ac23ba7c7a04c804dc4a9420a Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Fri, 30 Oct 2026 07:57:03 +0200 Subject: [PATCH 1/3] Backend: close a never-run body writer before sending the HTTP/1 head A bodiless streamed response (HEAD, 204, 304) wrote its head first and closed the writer afterwards, so a client could act on the response while the writer still held its resources. HttpStreamingTest's aWriterTheServerNeverRunsIsClosed lost that race on master CI. Co-Authored-By: Claude Opus 5.5 --- vm/backend/src/com/codename1/backend/HttpServer.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/vm/backend/src/com/codename1/backend/HttpServer.java b/vm/backend/src/com/codename1/backend/HttpServer.java index 4de80ae5f51..4933beb13b5 100644 --- a/vm/backend/src/com/codename1/backend/HttpServer.java +++ b/vm/backend/src/com/codename1/backend/HttpServer.java @@ -9271,15 +9271,20 @@ private void writeHeadAndBody(Conn conn, int fd, long session, Response response } if (streamed) { + // A writer that will never run is closed BEFORE the head goes out, not + // after. Once the client has the head it may act on the response, and a + // close that follows the write was observed losing that race (the + // writer's resources were still held when the client moved on). + if (noBody) { + response.discard(); + } try { writeTo(fd, session, conn.out, 0, conn.outLength); } catch (IOException | RuntimeException headFailed) { response.discard(); throw headFailed; } - if (noBody) { - response.discard(); - } else { + if (!noBody) { ResponseOutput output = new ResponseOutput(fd, session, chunked, null, 0); //NOPMD CloseResource - complete flushes on success; failure must abort and the connection owns the socket. response.bodyWriter.writeTo(output); output.complete(); From 1263904407814e16c28f798c2b21b08b998ea22d Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Fri, 30 Oct 2026 08:09:06 +0200 Subject: [PATCH 2/3] CI: add swap on the x64 Linux native suite too The x64 leg ran out of memory compiling the grown hello suite, the same failure arm64 already had swap for. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/linux-build-run.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/linux-build-run.yml b/.github/workflows/linux-build-run.yml index faf61d9f108..985572cd741 100644 --- a/.github/workflows/linux-build-run.yml +++ b/.github/workflows/linux-build-run.yml @@ -238,9 +238,10 @@ jobs: # The suite's C build compiles ~7,000 translation units, several of them # large, with full debug info. On ubuntu-24.04-arm it exhausted memory and # the runner was shut down mid-build, twice at the same step; extra swap - # lets the peak spill instead of taking the machine down. - - name: Add swap (arm64) - if: matrix.arch == 'arm64' + # lets the peak spill instead of taking the machine down. x64 joined it once + # the suite grew (#6118, #6106): every x64 run since went silent in + # `cmake --build` and was shut down about an hour in, while arm64 passed. + - name: Add swap run: | free -m sudo fallocate -l 12G /cn1-swapfile From f76966b5fed878af043585c7bde6eb209a4337bb Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Fri, 30 Oct 2026 08:10:28 +0200 Subject: [PATCH 3/3] Review: state the close-ordering contract; log disk headroom beside swap Co-Authored-By: Claude Opus 5.5 --- .github/workflows/linux-build-run.yml | 5 ++++- vm/backend/src/com/codename1/backend/HttpServer.java | 7 +++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/linux-build-run.yml b/.github/workflows/linux-build-run.yml index 985572cd741..0ef45ca792e 100644 --- a/.github/workflows/linux-build-run.yml +++ b/.github/workflows/linux-build-run.yml @@ -240,9 +240,12 @@ jobs: # the runner was shut down mid-build, twice at the same step; extra swap # lets the peak spill instead of taking the machine down. x64 joined it once # the suite grew (#6118, #6106): every x64 run since went silent in - # `cmake --build` and was shut down about an hour in, while arm64 passed. + # `cmake --build` and was shut down about an hour in, while arm64 passed -- + # the arm64 symptom exactly. `df` is here so a recurrence shows whether the + # disk, not memory, is what ran out. - name: Add swap run: | + df -h / free -m sudo fallocate -l 12G /cn1-swapfile sudo chmod 600 /cn1-swapfile diff --git a/vm/backend/src/com/codename1/backend/HttpServer.java b/vm/backend/src/com/codename1/backend/HttpServer.java index 4933beb13b5..8354a9d831f 100644 --- a/vm/backend/src/com/codename1/backend/HttpServer.java +++ b/vm/backend/src/com/codename1/backend/HttpServer.java @@ -9271,10 +9271,9 @@ private void writeHeadAndBody(Conn conn, int fd, long session, Response response } if (streamed) { - // A writer that will never run is closed BEFORE the head goes out, not - // after. Once the client has the head it may act on the response, and a - // close that follows the write was observed losing that race (the - // writer's resources were still held when the client moved on). + // A bodiless response's writer is closed before the head is written, so + // the close happens-before anything the client does after reading the + // status. Closing it after the write let the client run ahead of it. if (noBody) { response.discard(); }