Skip to content

fix(interpreter): model bash fork suppression for $SHLVL - #2636

Merged
chaliy merged 1 commit into
mainfrom
claude/shlvl-nofork
Oct 8, 2026
Merged

chaliy merged 1 commit into
mainfrom
claude/shlvl-nofork

Conversation

@chaliy

@chaliy chaliy commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Requested by Михайло · project thread

What changed

  • $SHLVL follows bash's fork suppression: when bash would run a command in place (last simple command of a bash -c string, of ( ), $( ), <( ), a background simple command, or exec bash outside ( )), a bash/sh child keeps the parent's level instead of adding one.
  • Not lowered where bash forks: { } groups, pipelines, if/case, functions, commands with redirects (outside a sole-command subshell), or when an EXIT/ERR/signal trap is set in that shell.
  • bash/sh children no longer inherit the parent's trap handlers (only ignored signals), so bash -c 'trap "echo bye" EXIT; bash -c true' prints bye once.

Why

Level-up roadmap, fidelity step: closes the shlvl-nesting bash-oracle gap (was L-PROC-003).

Before / After (verified)

bash-oracle: match 101 → 102, strict 99 → 100 / 106. floor.txt raised to 102 100.

unset SHLVL
bash -c 'bash -c "echo \$SHLVL"'
bash -c 'x=$(bash -c "echo \$SHLVL"); echo $x; { bash -c "echo \$SHLVL"; }'
bash -c 'trap "echo bye" EXIT; bash -c true'
output
bash 5.2 1 1 2 bye
this branch 1 1 2 bye
main (oracle case) nested levels one too high, e.g. 2 for the first line; bye printed twice

Risk

  • No new .await points in the hot path; stack for depth_32_no_stack_overflow is unchanged vs main (1849 KiB both).
  • Remaining gaps recorded in L-PROC-003: non-shell commands run in place (printenv SHLVL) still see the unlowered value; env bash/timeout bash in place are not lowered; a SHLVL=n prefix on the in-place command wins over bash's lowering.

Checklist

  • Failing tests first (shlvl.test.sh, 7 cases), verified against bash 5.2
  • fmt, clippy, integration, lib, CLI, bash_comparison, check-okf
  • knowledge updated (log, limitations)

Generated by Claude Code

bash execs the last simple command of a -c string, $( ) body, ( ) or <( )
body, and any simple command run with &, in place; a shell started there
lowers SHLVL first and keeps the level. exec bash does too, except
directly inside ( ). Child shells no longer inherit trap handlers.
@chaliy chaliy self-assigned this Oct 8, 2026
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
bashkit 37bef7f Commit Preview URL

Branch Preview URL
Oct 08 2026, 09:01 AM

@chaliy
chaliy merged commit 373bf8e into main Oct 8, 2026
46 checks passed
@chaliy
chaliy deleted the claude/shlvl-nofork branch October 8, 2026 09:22
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