From c34585cd72f1de92cb467c3b3c679a063a6998c7 Mon Sep 17 00:00:00 2001 From: stroblme Date: Mon, 24 Aug 2026 14:55:59 +0200 Subject: [PATCH] Retire a worker whose pipe broke rather than hand it on poll() still calls a child that has exited but not been reaped alive, so a node that ended itself with os._exit left its corpse on the idle queue and the next call died on a broken pipe. Mark it the way the out-of-step paths already do, and _release replaces it. Co-Authored-By: Claude Opus 5 (1M context) --- backend/fluksio/flow/workers.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/fluksio/flow/workers.py b/backend/fluksio/flow/workers.py index 12346bd..00b7d8e 100644 --- a/backend/fluksio/flow/workers.py +++ b/backend/fluksio/flow/workers.py @@ -391,6 +391,10 @@ class PythonWorkerPool: try: worker.send({**payload, "id": request_id}) except OSError as exc: + # A broken pipe is the truthful signal here: poll() still reports a + # child that has exited but not yet been reaped as alive, so + # _release would hand this corpse to the next call. Retire it. + worker.cancelled = True raise RemoteError(f"worker died: {exc}") from exc while True: @@ -433,6 +437,7 @@ class PythonWorkerPool: if line is None: worker.kill() raise NodeTimeout(f"was silent for {timeout}s and was killed") + worker.cancelled = True raise RemoteError("worker died") def compile(