Skip to content

fix(spawn): windows argv bridging in the tebako spawn hook (spec 22 §3.2) - #102

Merged
ronaldtse merged 1 commit into
mainfrom
fix/win-spawn-argv-bridge
Aug 27, 2026
Merged

fix(spawn): windows argv bridging in the tebako spawn hook (spec 22 §3.2)#102
ronaldtse merged 1 commit into
mainfrom
fix/win-spawn-argv-bridge

Conversation

@ronaldtse

Copy link
Copy Markdown
Contributor

Summary

Windows argv bridging in the tebako spawn hook — closes the last gap in the windows java-spawn chain (packed-mn v1.16.9 acceptance).

The failure this fixes: after tebako#485 (host tier, shipped in tebako v0.3.2) java.exe spawns fine on windows, but Jing failed with error: Error: Unable to access jarfile A:/__tfs__/lib/ruby/gems/3.3.0/gems/ruby-jing-0.0.3/lib/jing-20091111.jar — the child runs plain-host (windows has no child-side libtfs preload interposer; POSIX children inherit it) and cannot read VFS paths handed to it as argv strings.

Both known callers are shell-form spawns: jing uses backticks; mn2pdf's Jvm.run does ["java",*options,"-jar",MN2PDF_JAR_PATH,*args].join(" ")Open3.capture3.

What the patch does

In patches/<line>/process_c_tebako_spawn.patch, the existing tfs_spawn_prepare seam had #ifndef _WIN32 carrying the whole POSIX hook body with a no-op macro on windows. This replaces the windows no-op with the real implementation:

  • Shell form: tokenize the command line on unquoted blanks honoring double-quoted regions; separators preserved byte-exact; any token that names an embedded path (tebako_path_is_embedded) is materialized parent-side via tebako_fs_exec_materialize and rewritten to the host twin; bridged tokens are always re-quoted.
  • Array form: rebuild invoke.cmd.argv_buf (NUL-separated) and then rebuild argv_str exactly as rb_exec_fillarg does.
  • Exec target: embedded absolute exec-target materialization mirrors the POSIX rule.
  • Uses only the ungated C ABI (tebako_path_is_embedded, tebako_fs_exec_materialize in crates/tfs/src/c_api.rs) — no product-repo change; the fix is 100% in the ruby patch layer.

Validation

  • ruby tools/lint <ver> clean on all five lines: 3.1.7 / 3.2.11 / 3.3.12 / 3.4.10 / 4.0.6 (the five patch files were byte-identical pre-edit; ported by copy).
  • Local behavioral harness (mocked C ABI, gcc -Wall -Wextra clean) pins: jing and mn2pdf shell shapes, all-host byte-identity pass-through, quoted tokens with spaces, -Dcp=A:/__tfs__/x.jar embedded-substring correctly NOT bridged (whole-token rule), separator preservation.
  • 4.0.6 process.c verified field-compatible (invoke.cmd.argv_buf, invoke.sh.shell_script).
  • Acceptance (tonight's CI chain): packed-mn#251 windows leg — metanorma → jing (RNG validation via java+jar) → mn2pdf PDF compile.

Notes

  • Spec-22 amendment documenting the argv-bridge contract follows in the product repo after acceptance (doc-sync doctrine).
  • Layer 1 (host-side spawn of java.exe) shipped in tebako v0.3.2 (tebako#485); this PR is layer 2.

…3.2)
The host tier (tebako#485) materializes a dependency's exes and leads
PATH, so a bare-name spawn resolves — but the child runs plain-host and
cannot read VFS paths passed as ARGUMENTS. The packed-mn windows
acceptance died on exactly that: java.exe ran, then "Unable to access
jarfile A:/__tfs__/.../jing-20091111.jar" (POSIX never sees this — the
child inherits the libtfs preload).
Replace the win32 no-op in the tfs_spawn_prepare seam with the bridge:
argument tokens naming embedded paths materialize parent-side through
tebako_fs_exec_materialize and rewrite to the host twin — shell-form
command lines (tokenized on unquoted blanks, separators preserved,
bridged tokens re-quoted) and array form (argv_buf + the argv_str
pointer vector rebuilt exactly as rb_exec_fillarg built them), plus
embedded exec-target materialization by the POSIX hook's rule.
Non-embedded tokens and unheld paths pass through byte-identical and
honestly.
Validated: tools/lint clean on 3.1.7/3.2.11/3.3.12/3.4.10/4.0.6; a
local behavioral harness (mocked ABI) pins the jing/mn2pdf shapes,
all-host byte-identity, quoted-with-spaces tokens, embedded-substring
non-bridging, and separator preservation. The factory windows leg plus
the packed-mn acceptance is the end-to-end gate.
@ronaldtse
ronaldtse merged commit 21391fe into mainAug 27, 2026
42 checks passed
ronaldtse pushed a commit that referenced this pull request Aug 27, 2026
…hadowing)
process_c_clock_guard_msys (lines 3.2/3.3/3.4) shadows the base
process_c_tebako_spawn under PatchSelection's msys rule (a base patch
is dropped when an _msys sibling targets the same file), so windows
runtimes have never carried the spawn hook — including the argv bridge
merged in #102. Add the msys variant (identical content; the POSIX
half compiles out under _WIN32) so the bridge actually lands on msys.
3.1/4.0 have no clock_guard patch and keep the base, verified via
PatchSelection for 3.1.7/3.2.11/3.3.12/3.4.10/4.0.6 + scenario
composition proofs (tools/apply --platform msys --pass 2).
Sign up for freeto 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.

2 participants

@ronaldtse@tebako-ci