Repository navigation
fix(procsub): =(cmd) takes a fresh temp name, never one a dead shell left - #160
Merged
Merged
Conversation
…left
zsh_glob_test's eqsub/reads-back failed in a local pty gate run:
cat =(echo hi) -> no output, status 0, no error
About one run in 150 does this on develop, and on a 3.1.0 build too.
strace of a failing run:
openat("/tmp/hsh2222-0", O_RDWR|O_CREAT|O_EXCL) = -1 EEXIST
The name was /tmp/hsh<pid>-<n>. A =(cmd) made inside $( ) outlives its
subshell, so /tmp keeps such files from processes long gone (88 of them
here, 2 more on every run of the suite). A later shell given the same
pid found its name taken. The O_EXCL open failed, create_procsub_file
returned NULL, the word vanished without a word, and `cat` ran with no
argument and read its stdin instead.
The name now comes from mkstemp: TMP_DIR/hsh.XXXXXX, still O_EXCL and
0600, and a taken name is retried rather than fatal. If the file cannot
be created at all, the shell says so ("=(...): cannot create a
temporary file: <reason>") instead of dropping the word silently.
tests/zsh_procsub_test.py gains the collision itself, made
deterministic: the script creates /tmp/hsh$$-0 and -1 first, then runs
`cat =(echo hi) </dev/null`. develop prints nothing; this prints hi.
The original loop, `cat =(echo hi)` 300 times, goes from 1 or 2 empty
runs to 0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RAmeHfJNm7XjYbMNrQqvkG
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What & why
zsh_glob_test'seqsub/reads-backfailed in a local pty gate run:cat =(echo hi)printed nothing, exited 0 and reported no error. It happens about once in 150 runs, on develop and on a 3.1.0 build as well.strace of a failing run:
Root cause.
/tmp/hsh<pid>-<n>.=(cmd)made inside$( )outlives its subshell, so/tmpkeeps files from processes long gone: 88 of them in this container, 2 more after every suite run.O_EXCLopen failed.create_procsub_filethen returned NULL and the word vanished without any message.catran with no argument and read its stdin instead.Change (
src/platform/posix/procsub_file.c):mkstemp, asTMP_DIR/hsh.XXXXXX. It is still exclusive and mode 0600, and a name that is already taken is retried instead of being fatal.=(...): cannot create a temporary file: <reason>) instead of silently dropping the word.This is the flake mentioned in #157's verification notes.
How I verified it
tests/zsh_procsub_test.pygains the collision itself: the script creates/tmp/hsh$$-0and/tmp/hsh$$-1first, then runscat =(echo hi) </dev/null. develop prints nothing; this branch printshi.cat =(echo hi)300 times, goes from 1 or 2 empty runs to 0.tests/tester: 5363/5363;tests/run_scripts.shagainstbash --posix: 125/125;verify_alloc.sh: identical output on both heaps;alloc_stress.sh: all clean;tests/pty_suite.sh: 111 ok, 6 skipped, 4 failed, withzsh_procsub_testandzsh_glob_testamong the passes. None of the four failures is this change:prompt_compat_matrix,prompt_drift_matrixandprompt_jobs_badgeexpect the non-root%/$prompt and get#, because the container runs as root. They fail the same way on develop, and CI runs them as a normal user.hxp_framework_testhit the 420 s per-file limit on this 4-core container. develop's binary takes 440 s for it on the same machine, and CI's runners finish it inside the limit.norminetteis OK on the touched file.Notes / trade-offs
src/parsed that name. Cleanup is unchanged: the session still removes every file it recorded.=(cmd)made inside$( )still leaves its file in/tmpwhen that subshell exits. This PR makes those leftovers harmless; removing them is a separate change, in how a subshell hands off its cleanup list.🤖 Generated with Claude Code
https://claude.ai/code/session_01RAmeHfJNm7XjYbMNrQqvkG
Generated by Claude Code