In the browser on brintos.io/emcraft/linux-6.12-musl-bash-coreutils, a spawned child's pty I/O does not flow: expect's first spawn hangs indefinitely — not even Expect's own timeout fires. The Tcl self-test passes in the same browser session (ALL-TCL-OK), so kernel, musl, Tcl_Init, encodings, and access(2) all work — the problem is specifically the pty master↔slave I/O for a spawned child.
Reproduction (browser)
tclsh /root/selftest.tcl → ALL-TCL-OK
expect /root/selftest_expect.exp → prints "E-E1ver OK", then hangs at the first spawn
Minimal, with an explicit timeout that should fire but doesn't:
expect -c 'set timeout 5; spawn /bin/cat; send "HI\r"; expect { "HI" {puts OK} timeout {puts TIMEOUT} }'
# browser: hangs, no output (not even TIMEOUT). fra2: prints OK.
Evidence it is host-side, not the image
The identical rootfs + kernel bytes pass an Expect self-test 5/5 fresh boots on fra2 via run-machine.mjs against hardwarejs 63a34b9. Our client-side Expect fixes (dup2 for the pty-slave stdout/stderr wiring, openpty, ptsname) are compiled into the deployed /bin/expect — the same binary that ran Tcl fine in the browser. The only variable between the passing fra2 run and the hanging browser run is the host worker / its runtime.
The hang with no timeout (rather than an EBADF or a TIMEOUT) points at the pty read/write/poll for the spawned child never being serviced — the master↔slave coupling between the expect process and its child.
Not the same as the two already filed
- hardwarejs#1 (
fcntl(F_DUPFD)returns ENOSYS on non-console kernel fds) — we worked that around client-side withdup2, so it is not the browser blocker. - linux-in-the-browser#47 (a spawned child's coroutine drive traps after ~2 blocking-read exchanges) — the browser hangs at the first spawn, before that limit applies.
This is the actual blocker for Expect browser-green.
Two hypotheses to disambiguate
You have the served build + the browser runtime, so you can tell which:
- (a) the served worker lags fra2's
63a34b9for the spawn/pts read/write/pollrouting (theK12-A/D1-FD/ blocking-tty-read paths), or - (b) a browser-specific cross-Worker pts coupling issue (real Web Workers + SharedArrayBuffer) that does not manifest under fra2's Node
run-machineruntime even at the same63a34b9.
Happy to run any probe you want on either side (fra2 or a deployed browser machine).