Skip to main content

execpline

Function execpline 

Source
pub fn execpline(
    state: &mut estate,
    slcode: wordcode,
    how: i32,
    last1: i32,
) -> i32
Expand description

Port of execpline(Estate state, wordcode slcode, int how, int last1) from Src/exec.c:1724-2041. Full faithful port: allocates a job-table entry via initjob, sets up coproc mpipes, drives the whole (multi-stage) pipeline through execpline2 (which performs the real per-stage mpipe/fork/exec), then either spawns the job asynchronously (Z_ASYNC -> spawnjob/deletejob) or waits synchronously (waitjobs), including the list_pipe stop/continue fork machinery (SUBJOB/SUPERJOB linkage) that re-forks the shell to keep an interactively-suspended right-hand pipeline stage running.

Divergences from C, each forced by the Rust substrate and cited inline at the point of use:

  • initjob here grows the Vec-backed jobtab on demand and does not return -1, so C’s per-pipeline table-full bailout (c:1756-1760) is inert on THIS path. That bailout is zsh’s universal recursion backstop (initjob caps the table at MAX_MAXJOBSzerr("job table full or recursion limit exceeded")), which bounds recursion through paths FUNCNEST does not count (sourced files, eval — the doshfunc funcnest check at c:5684 counts FS_FUNC frames only). The fusevm runtime that actually executes pipelines does not allocate a job per pipeline, so that backstop was missing entirely — runaway source/eval recursion overflowed the (large but finite) main-thread stack → SIGBUS. It is reinstated inline (same ceiling, total FUNCSTACK depth as the proxy for held job slots) at the FS_SOURCE re-entry (init.rs::source) and FS_EVAL re-entry (builtin.rs eval).
  • errbrk_saved / prev_errflag / prev_breaks (jobs.c:128 globals) are only read here; their setter lives in the not-yet-ported jobs.c reaping path, so they stay 0 and the if (errbrk_saved) restore (c:1998-2003) is a faithful no-op.