Skip to content

Fix #256: close subprocess stdin so reads see EOF (aspect CLI hang)#351

Merged
tinder-maxwellelliott merged 2 commits into
masterfrom
claude/reproducer-issue-256
May 15, 2026
Merged

Fix #256: close subprocess stdin so reads see EOF (aspect CLI hang)#351
tinder-maxwellelliott merged 2 commits into
masterfrom
claude/reproducer-issue-256

Conversation

@tinder-maxwellelliott
Copy link
Copy Markdown
Collaborator

@tinder-maxwellelliott tinder-maxwellelliott commented May 15, 2026

Summary

Fixes #256 (cross-posted at aspect-build/aspect-cli-legacy#41): bazel-diff froze forever when .bazeliskrc was set to download aspect CLI, with a FUTEX_WAIT on the Java process.

Root cause

cli/src/main/kotlin/com/bazel_diff/process/Process.kt built the subprocess with ProcessBuilder(*command).start() and never redirected or closed stdin. ProcessBuilder defaults redirectInput to Redirect.PIPE, so the subprocess received an open, never-fed stdin pipe. Any subprocess that called read(stdin) on startup — which aspect CLI v1's interactive first-run path does — blocked indefinitely, the parent lineFlow-on-stdout never saw EOF, and process.waitFor() parked forever.

Fix

Close process.outputStream immediately after start() so the subprocess sees EOF on stdin. This mirrors what ExternalRepoResolver.runProcessAndCaptureFirstLine already does, and is preferred over redirectInput(Redirect.from(File("/dev/null"))) because it works cross-platform without hard-coding a device path.

Regression test

The original @Ignored reproducer (first commit on this branch) is now flipped into a real regression test and renamed to ProcessStdinHangRegressionTest to match the codebase's *RegressionTest convention (cf. StderrPollutionRegressionTest). It spawns cat (a minimal subprocess that blocks on stdin) and asserts the call completes within 5s with resultCode == 0. Without the fix the timeout fires; with the fix the test passes in ~0.1s.

Test plan

  • bazel test //cli:ProcessStdinHangRegressionTest — passes in ~0.4s with the fix.
  • Reverted just the Process.kt hunk locally and re-ran the test — it timed out at the 5s mark and assertNotNull failed, confirming the test still catches the regression.
  • bazel test //cli/... (excluding E2ETest, which fails locally on this machine with an unrelated JDK sandbox auto-config error both before and after this change) — all 14 unit tests pass, including the new regression test.
  • CI to validate E2ETest end-to-end.

🤖 Generated with Claude Code

tinder-maxwellelliott and others added 2 commits May 15, 2026 05:08
Adds an @ignore'd JUnit reproducer that demonstrates the most likely
underlying cause of #256 (bazel-diff freezes when aspect CLI is
installed). `process()` calls `ProcessBuilder.start()` without ever
redirecting or closing the subprocess's stdin pipe, so any subprocess
that reads from stdin (as the aspect CLI v1's interactive first-run
path appears to do) blocks forever waiting for input.

The test spawns `cat` (which blocks on stdin read), wraps the call in
`withTimeoutOrNull(5_000)`, and asserts the result is null — proving
the deadlock. Confirmed locally: with @ignore removed, the test runs
exactly 5s and passes; with @ignore in place CI stays green.

No production code change in this PR. The fix is intentionally
out-of-scope; this PR just locks in a regression target for whoever
picks up the work on #256.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`process()` started subprocesses via `ProcessBuilder.start()` without
redirecting or closing stdin. Java defaults stdin to `Redirect.PIPE`,
so the subprocess received an open, never-fed pipe; any subprocess
that read from stdin on startup (e.g. aspect CLI's interactive
first-run path) blocked forever on `read()`, and `process.waitFor()`
blocked too — matching the user-reported `FUTEX_WAIT` strace.

Close `process.outputStream` immediately after `start()` so the
subprocess sees EOF on stdin, mirroring what
`ExternalRepoResolver.runProcessAndCaptureFirstLine` already does.

Flip the @ignore'd reproducer into a real regression test and rename
it to `ProcessStdinHangRegressionTest` to match the codebase's
`*RegressionTest` convention. The test now asserts that `cat` exits
cleanly within the 5s timeout — without the fix it hangs and the
timeout fires.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tinder-maxwellelliott tinder-maxwellelliott changed the title Reproducer test for #256 bazel-diff freezes with aspect CLI (stdin not closed) Fix #256: close subprocess stdin so reads see EOF (aspect CLI hang) May 15, 2026
@tinder-maxwellelliott tinder-maxwellelliott merged commit 38b853c into master May 15, 2026
15 checks passed
@tinder-maxwellelliott tinder-maxwellelliott deleted the claude/reproducer-issue-256 branch May 15, 2026 15:48
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.

bug: bazel-diff freezes when aspect CLI is installed

1 participant