Skip to content
This repository was archived by the owner on Jul 17, 2026. It is now read-only.

fix(run): exit after profile.async_test — donation has consumed state#968

Open
claude-spd1 wants to merge 1 commit into
feature/jaxfrom
bridge/task-fix-async-test-donated-state
Open

fix(run): exit after profile.async_test — donation has consumed state#968
claude-spd1 wants to merge 1 commit into
feature/jaxfrom
bridge/task-fix-async-test-donated-state

Conversation

@claude-spd1

Copy link
Copy Markdown
Collaborator

Description

profile.async_test (run.py) calls the donating step_fn (donate="all-except-first") three times starting from state and never rebinds it — results land in locals while state keeps naming the donated (deleted) buffers. Control then falls through to the mem_profile path and the main training loop, which die with "Array has been deleted" the moment they touch state.

Two changes, mirroring how the mem_profile path already guards the identical situation:

  • os._exit(0) at the end of the async_test block (same guard + comment as mem_profile's at the end of its block).
  • A ProfileConfig validator refusing async_test + mem_profile in one config — each hook now exits before the loop, so combining them would silently skip whichever runs second. Refuse at config-parse time instead.

Related Issue

Audit finding M2 from the 2026-07-10 JAX compile audit (latent correctness, profiling flag only). Refs against feature/jax @ eb786f7.

Motivation and Context

async_test alone happened to work only because nothing after it ran; combined with a normal run or mem_profile it was a guaranteed crash. Precedent for loud donation guards: PR #932 (resume-oom donation fix).

How Has This Been Tested?

  • New test_config.py::test_profile_exiting_hooks_are_mutually_exclusive pins the validator (each flag alone validates; together refuses). param_decomp/tests/test_config.py passes (15/15).
  • Pre-commit ruff + basedpyright clean.
  • The exit guard itself is the same one-liner the mem_profile path has carried; not exercised on GPU (profiling-only path).

Does this PR introduce a breaking change?

No. A config setting both async_test: true and mem_profile: true now refuses at validation — previously it would have crashed mid-run instead.

Crew-Address: task/fix-async-test-donated-state

🤖 Generated with Claude Code

The async_test block calls the donating step_fn (donate=all-except-first)
on `state` without rebinding it, then fell through to the mem_profile path
and the main loop holding deleted buffers — guaranteed "Array has been
deleted" whenever async_test was combined with a normal run. Mirror the
mem_profile guard: os._exit(0) at the end of the block, plus a
ProfileConfig validator refusing async_test+mem_profile together (each
exits before the other could run).

Audit finding M2 (2026-07-10 compile audit).

Crew-Address: task/fix-async-test-donated-state

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant