Skip to content

fix(interpreter): run coprocesses concurrently over in-process pipes - #2638

Merged
chaliy merged 1 commit into
mainfrom
claude/coproc-streaming
Oct 8, 2026
Merged

chaliy merged 1 commit into
mainfrom
claude/coproc-streaming

Conversation

@chaliy

@chaliy chaliy commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

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

What changed

  • coproc runs its body as a background job alongside the shell, connected by two bounded in-process pipes (the same pipes pipeline stages use). Writes to ${NAME[1]} feed its stdin, closing the write end delivers EOF, reads from ${NAME[0]} get its output.
  • Request/response loops work without deadlock; read -u, wait $NAME_PID (returns the body's status), $!, jobs, the default name COPROC, bash's fd numbers (63 60) and the "still exists" warning match bash.
  • After wait reaps a coproc, NAME/NAME_PID are unset and its fds closed. exec() closes unclosed coprocs so a call can't hang.
  • <&$x with an empty $x is now an error instead of silently reading stdin.

Why

Level-up roadmap, concurrency/streaming step: closes the coproc-basic bash-oracle gap.

Before / After (verified)

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

coproc-basic (coproc UPPER { tr a-z A-Z; }, write, close, read): main printed an empty line, bash and this branch print TEXTO.

coproc C { while read l; do echo "got $l"; done; }
for i in 1 2; do echo "q$i" >&"${C[1]}"; read -r r <&"${C[0]}"; echo "$r"; done
exec {C[1]}>&-
wait $C_PID; echo rc=$?

bash 5.2 and this branch: got q1 / got q2 / rc=0.

Risk

  • Each coproc takes a background-job slot (TM-DOS-122) and two persistent fds (TM-DOS-063); pipes are bounded (4 KiB plus one command's output). With concurrent_jobs(false) the body runs to completion at coproc with stdin at EOF.
  • No new awaits in hot async fns; stack for depth_32_no_stack_overflow is identical to main.
  • Remaining gaps in L-PROC-005: a finished coproc stays until wait (bash reaps on SIGCHLD); a coproc fd as a compound command's stdin is read up front; read -n on a coproc fd consumes the whole line; writes after exit are dropped instead of SIGPIPE.

Checklist

  • Failing tests first (coproc_tests.rs), verified against bash 5.2
  • fmt, clippy, integration, lib, terminal, CLI, bash_comparison, rustdoc, check-okf
  • knowledge updated (parallel-execution, limitations, threat-model, log)

Generated by Claude Code

coproc bodies ran once at `coproc` with empty stdin, so writes to
${NAME[1]} were lost (bash-oracle coproc-basic printed an empty line).
A coproc is now a background job wired to the shell through two bounded
pipes: writes feed its stdin, closing the write end delivers EOF, reads
of ${NAME[0]} take its output line by line. bash fd numbering, the
still-exists warning, NAME/NAME_PID cleanup after wait, and exec()
closing the shell's ends before waiting for jobs.
@chaliy chaliy self-assigned this Oct 8, 2026
@cloudflare-workers-and-pages

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 19c5074 Commit Preview URL

Branch Preview URL
Oct 08 2026, 10:14 AM

@chaliy
chaliy merged commit c351741 into main Oct 8, 2026
46 checks passed
@chaliy
chaliy deleted the claude/coproc-streaming branch October 8, 2026 10:42
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