Skip to content

spawn plan head: offer the plan only the user arguments, never argv[0] (#669) - #119

Merged
ronaldtse merged 1 commit into
mainfrom
fix/spawn-plan-argv0
Sep 26, 2026
Merged

ronaldtse merged 1 commit into
mainfrom
fix/spawn-plan-argv0

Conversation

@ronaldtse

Copy link
Copy Markdown
Contributor

What

Both array-form call sites of the spec-30 spawn plan head (POSIX hook + windows hook) passed ruby's invoke.cmd.argv_buf to tebako_spawn_runtime_plan including its first token — the child argv[0] that rb_exec_fillarg packs. The plan composes [exe, --tebako-image…, --tebako-entry, <name>, <args…>], so the spawned runtime received the program name as its first user argument. For the java engine edge the JVM gets java as its main class:

Error: Could not find or load main class java
Caused by: java.lang.ClassNotFoundException: java

How it stayed latent

Every real-world engine spawn was shell form until now (the shell bridge takes a different code path). ruby-jing 0.1.0 switched from backticks to Open3.capture2e(*argv) — argv form, made upstream specifically for tebako-like environments (no /bin/sh reachability). The metanorma 1.17.0 payload carries it; the dogfood full-compile legs fail at the RELAX NG validation step on macOS + linux (nightly run 36230144734; the 1.16.9 payload with ruby-jing 0.0.3 shell form was green the night before).

Fix

At both call sites, advance past argv_buf's first NUL-terminated token before packing args — the plan supplies the entry name itself via --tebako-entry. A custom argv0 (the [cmd, name] array form) is likewise never a user argument. The 3.2/3.3/3.4 msys carriers get the byte-identical diff payload (parity spec enforced).

Closes the source-factory half of tamatebako/tebako#669.

Validation

  • tools/apply apply-clean with the fix present in process.c, latest version of every line (3.1.7, 3.2.11, 3.3.12, 3.4.10, 4.0.7) × darwin + msys
  • bundle exec rspec 116 examples, 0 failures (incl. the msys byte-parity gate)
  • End-to-end proof lands with the next tebako-runtime-ruby build: the metanorma dogfood's jing leg goes green on a fixed runtime (no payload repin needed — the ABI-line resolution picks up the newest compatible runtime)

Draft rationale

Draft per the ecosystem rule: merging to main is owner-gated. The downstream chain on merge: source-factory tarball → tebako-runtime-ruby rebuild (new runtime release) → dogfood re-run.

ruby's rb_exec_fillarg packs the FULL argv into invoke.cmd.argv_buf —
first token included. Both array-form call sites (the POSIX hook and
the windows hook) handed that buffer to tebako_spawn_runtime_plan
verbatim, so the plan's `args` began with the program name. The plan
then composed the child argv as

  [exe, --tebako-image..., --tebako-entry, <name>, "java", "-jar", ...]

and the spawned runtime exec'd its entrypoint with the program name as
its first USER argument — for the java edge the JVM receives `java` as
its main class:

  Error: Could not find or load main class java
  Caused by: java.lang.ClassNotFoundException: java

Latent since the spec-30 spawn planner landed: every real-world engine
spawn was shell form (the shell bridge takes a different path), until
ruby-jing 0.1.0 switched to Open3.capture2e — argv form — which is
exactly the spawn shape tebako environments want (no /bin/sh). The
metanorma 1.17.0 payload carries ruby-jing 0.1.0; its dogfood
full-compile legs fail at the RELAX NG validation step on macOS and
linux alike (tebako-packages/metanorma nightly run 36230144734;
1.16.9 — ruby-jing 0.0.3, shell form — was green the night before).

Fix: at both call sites, advance past argv_buf's first NUL-terminated
token before packing `args` (a custom argv0 from the [cmd, name] form
is likewise never a user argument). The msys carriers
(3.2/3.4/3.4 lines) receive the byte-identical diff payload per the
parity spec.

Closes the source-factory half of tamatebako/tebako#669. Validated:
tools/apply apply-clean with the fix present in process.c for the
latest version of every line (3.1.7, 3.2.11, 3.3.12, 3.4.10, 4.0.7) on
darwin AND msys; bundle exec rspec 116/0 (incl. the msys byte-parity
gate). End-to-end proof lands with the next tebako-runtime-ruby build
(the metanorma dogfood's jing leg goes green on a fixed runtime).
@ronaldtse
ronaldtse marked this pull request as ready for review September 26, 2026 10:16
@ronaldtse
ronaldtse merged commit e060474 into main Sep 26, 2026
43 checks passed
ronaldtse added a commit to tebako-packages/metanorma that referenced this pull request Sep 26, 2026
…; harden gate probes

Merging with two red full-compile legs (aarch64-macos, x86_64-linux-gnu): both fail on tebako#669 (spawned java runtime receives argv[0]; CNFE 'main class java'). Root cause fixed at source in tamatebako/ruby#119 (v0.2.37); the fixed runtime publishes via the tebako-runtime-ruby chain. Main's nightly fails identically, so this merge does not regress main. This PR is the prerequisite for the flavor rebinds (packed-metanorma-bsi#3 / packed-metanorma-nist#3): their acceptance was failing on the python runtime registry entries still in the pre-rendezvous universal grammar.
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.

2 participants