fix(stall-watch): instrument, close MD5-verify gap, retry retrieve stalls #36
+795
−74
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up from the 2026-07-20 stall investigation (job 40937735,
repository_X1D_3_metabolomics_rawspectra): PR #32's stall-watch reliably killed 4prior identical
htar -xvfretrieve hangs at exactly "no output for 2.0h" — but thisone ran ~30 minutes past that bound with no way, after the fact, to tell whether that
was a genuine mechanism gap or a last-second activity reset (short of a live
strace/py-spycapture, which wasn't available). Implements recommendations 1-4from that report.
_run_with_stall_watch+send_to_fortress'sinline twin): a new
activity_logpath records a timestamped trail of everyactivity/poll event, but only once silence passes half of
stall_seconds— ahealthy multi-hour transfer leaves zero trace, so log_dir doesn't get littered.
Wired into every create/retrieve call site in both
ship_objectandsend_to_fortress. Closes the open question from the report for any recurrence.stall-guarded, but the pure-Python per-file MD5 comparison loop that runs after a
round-trip retrieve had no timeout of any kind — confirmed real by code read, not
speculated. Added
_run_callable_with_stall_watch/VerifyStallError, athread-based watchdog for blocking reads with no subprocess to terminate. Genuine
verification failures (mismatch, missing file) still raise/email exactly as
before; only a real stall raises the new type.
ship_object's round-trip retrievegets one automatic retry (
RETRIEVE_STALL_MAX_ATTEMPTS=2, 60s backoff) — but onlywhen the failure is specifically a stall-watch timeout, never a genuine extract
failure. 4 of 5 recent stalls on this object were the create succeeding and only
the retrieve hanging on a dead HPSS mover session (confirmed via
CLOSE_WAITsockets to
hpss-mvr03+ a futex-wedged client during the live investigation).investigation — unrelated to this diff, no code change needed for that.
Test plan
repeated runs (timing-sensitive tests use real subprocesses/threads with shrunk
stall_seconds/poll_interval, no mocking of subprocess itself, matching theexisting suite's convention)
modes (pipe + file-growth), the callable watchdog + exception propagation
(
VerifyStallErrorvs a genuine re-raised failure), and the retry/give-up/non-retry boundary cases for
ship_object's retrieve steppython3 -m pyflakes archive.py tests/clean of new issues🤖 Generated with Claude Code