Skip to content

Fix: worker and client lifecycle (F13 F17 F18 F19 F21) - #42

Merged
guijacquemet merged 4 commits into
mainfrom
claude/fix-lifecycle
Oct 8, 2026
Merged

guijacquemet merged 4 commits into
mainfrom
claude/fix-lifecycle

Conversation

@guijacquemet

Copy link
Copy Markdown
Contributor

Fixes the lifecycle theme of the round-trip findings; their cases now run as normal tests and the findings are removed from tests/roundtrip_known_failures.py.

Before -> after

  • F13: the worker attaches to the host's shared-memory block without registering it with its resource tracker (track=False on Python 3.13+, otherwise the tracker registration is skipped during the attach), so the host's block survives the worker and crash messages no longer carry the "leaked shared_memory" warning. The host still unlinks its own block.
  • F17: a request to a dead (or already closed) worker returns a task that is already CRASHED with the usual "worker exited unexpectedly (code N)", hint and worker output; it is not left registered and nothing raises.
  • F18: on POSIX the worker puts itself in its own process group at start (setsid, unless it already leads one) and, when stdin closes (or after ORPHAN_GRACE_S for a tool that ignores cancel), SIGKILLs every other member of the group, then exits normally. Members are found with ps -A -o pid=,pgid=; if ps fails it logs a warning and kills the whole group. Because the worker does this itself, no host change is required (Appose and ProcessBuilder cannot call setsid).
  • F19: progress is rounded to the nearest percent, ties up (floor(100 f + 0.5), like Java's Math.round): progress(0.29) shows 29 % (was 28), 0.99995 shows 100 %.
  • F21: on Windows a transient PermissionError (WinError 5) from os.replace in the registry's atomic write is retried (REPLACE_ATTEMPTS = 6, REPLACE_PAUSE_S = 0.2, each retry logged) and, if it persists, raises an error naming the file and saying an antivirus, indexer or viewer probably holds it. The test harness' registration retry is removed.

Existing-test exceptions (both approved, both named in commit 56606c0): test_roundtrip_failures.py::WhatAToolReturns.test_many_progress_messages_all_arrive_and_the_task_still_ends expected the truncated maximum 0.99 (now 1.0, with the reason in a comment); tests/test_sabotage.py: the progress break now patches the new rounding line and is guarded by test_every_whole_percent_arrives_as_itself. Dead is_known("lifecycle:...") skips were removed from two tests (strengthens them).

New tests/test_lifecycle_fixes.py (11 tests; the only OS-call mocks are the os.replace ones, which test our retry logic). Docs: PROTOCOL.md, REGRESSION_LEDGER.md.

Host follow-ups: progress: use current/maximum as sent, and round half up if a percent is computed from a fraction; hosts that write shared memory own the unlink; a task on a dead worker should be shown as CRASHED with the worker's output (Napari). Process group: Napari already starts the worker with start_new_session=True; Fiji (Appose Service) and QuPath (ProcessBuilder) rely on the worker's own setsid.

Verified by the author on Linux, Python 3.11: black, ruff, mypy, vulture; full suite 409 tests with only the two environmental sandbox failures; coverage 85.95 % (floor 85); sabotage passes. I re-ran black, ruff, mypy and the lifecycle and failure-injection tests. Not verified: F21 on real Windows, the track=False path on Python 3.13+, macOS (ps, process groups), and Fiji/QuPath with the worker's own setsid: the host regressions must be re-run against this Tools version before the hosts are considered green.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Y2SN8SuEakTdiWy3F2WUqN


Generated by Claude Code

claude added 4 commits October 8, 2026 12:42
…n a dead worker (F17), kill the process group when the host is gone (F18), round progress (F19), retry os.replace on Windows (F21)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y2SN8SuEakTdiWy3F2WUqN
…tage break re-pointed for rounding

Two existing tests are edited, with approval, because they encoded the F19 truncation bug:
- test_roundtrip_failures.WhatAToolReturns.test_many_progress_messages_all_arrive_and_the_task_still_ends: expected maximum 0.99 -> 1.0 (19999/20000 rounds to 100 %).
- tests/test_sabotage.py: the 'progress is off by one percent' break now patches math.floor(...) in worker._whole_percent and is guarded by test_every_whole_percent_arrives_as_itself.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y2SN8SuEakTdiWy3F2WUqN
…exit status 0, coverage written)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y2SN8SuEakTdiWy3F2WUqN
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants