Skip to content

fix(auth): retry spawn on ETXTBSY in the auth-status check - #815

Draft
benw5483 wants to merge 1 commit into
mainfrom
fix-auth-spawn-etxtbsy-retry
Draft

fix(auth): retry spawn on ETXTBSY in the auth-status check#815
benw5483 wants to merge 1 commit into
mainfrom
fix-auth-spawn-etxtbsy-retry

Conversation

@benw5483

Copy link
Copy Markdown
Contributor

Summary

  • Route both spawn sites in the claude auth status check through the existing spawn_with_etxtbsy_retry helper, so a freshly written executable no longer fails the exec with ETXTBSY ("text file busy").
  • Share one spawn_auth_child function between check_auth_async and check_auth_async_no_json, which previously duplicated the spawn and its error mapping verbatim.

Why

The runner spawn paths already retry on ETXTBSY; the auth-status check was the one that still called Command::spawn() directly. That gap surfaced as an intermittent failed to spawn claude: Text file busy (os error 26) panic in test_check_auth_async_success under the instrumented coverage build, which runs slowly enough to lose a race the plain Test job usually wins. A single panic there aborts lcov.info generation, so Coverage Enforcement fails with a missing-report error rather than a real per-file miss.

probe_claude_auth_async runs the same claude auth status --json command and was already covered, so this brings the two into line.

Test plan

  • cargo test --workspace --features integration — 3103 passed, 0 failed in the main crate; all nine integration suites green.
  • cargo fmt --check and cargo clippy -- -D warnings — both clean.
  • cargo llvm-cov reproducing the coverage job — cli/commands/auth.rs 552/552 lines and runner/util.rs 200/200, with every file in the tree at 100%.

The retry branch itself is already covered by the four unit tests on spawn_with_etxtbsy_retry in src/runner/util.rs: first-attempt success, retry-then-succeed, non-ETXTBSY error not retried, and retries exhausted. No new integration test provokes a real ETXTBSY, because it cannot be reproduced portably. Holding a writable file descriptor on a fixture script raises no error on macOS, so such a test would be Linux-only and timing-dependent, which is the opposite of what this change is for.


Generated by the operator's software factory.
• City: factory-main · Agent: local-core.builder-1
• On behalf of: @benw5483

A freshly written executable can transiently report ETXTBSY ("text file
busy") when a concurrent fork in another thread still holds a writable fd
to it across the fork->exec window. The runner spawn paths already route
through spawn_with_etxtbsy_retry; the auth-status check did not, so it
kept spawning the target binary directly.

That gap showed up as an intermittent 'failed to spawn claude: Text file
busy (os error 26)' panic in test_check_auth_async_success under the
instrumented coverage build, which is slow enough to lose the race the
plain test job usually wins. A single panic there aborts lcov.info
generation, so the coverage gate fails with a missing-report error rather
than a real per-file miss.

Route both auth spawn sites through the existing retry helper, sharing one
spawn_auth_child function so the two call sites no longer duplicate the
spawn and its error mapping. This mirrors probe_claude_auth_async, which
runs the same 'claude auth status --json' command and was already covered.

Generated by the operator's software factory.
City: factory-main · Agent: local-core.builder-1
On behalf of: @benw5483
Co-Authored-By: <operator-factory-bot> <factory-bot@actual.invalid>
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.

1 participant