Summary
posix_spawn(3) fails with ENOSYS ("Function not implemented") on the
wasm32-hwjs runtime (glibc arm), while plain vfork() + execve() works. glibc
implements posix_spawn() via clone(CLONE_VM | CLONE_VFORK | SIGCHLD) (the
shared-address-space vfork-style clone), so the gap looks like that specific
clone flag combination is not wired, even though ordinary fork()/vfork()
are (busybox and expect spawn children fine).
GNU make 4.3+ runs every recipe through posix_spawn() by default, so on this
runtime every recipe dies immediately — the tool is otherwise fully
functional (parses Makefiles, resolves the DAG, prints its version).
Reproduction
On a glibc core-image-brintos-emcraft machine that ships GNU make (booted in
the browser):
$ cat > /tmp/Makefile <<'EOF'
all:
@echo HELLO-FROM-MAKE
EOF
$ make -C /tmp
make: echo: Function not implemented
make: *** [Makefile:2: all] Error 127
A recipe with shell metacharacters routes through /bin/sh -c and fails the same
way:
$ make -C /tmp out.txt # rule: out.txt: \n\t@echo BODY > $@
make: /bin/sh: Function not implemented
make --version works (GNU Make 4.4.1), so make itself is loaded and running —
only child spawning fails.
Evidence — it is posix_spawn, not fork/exec in general
Process creation itself works on this runtime; the failure is specific to the
posix_spawn path:
- busybox shell pipelines,
find … | xargs, andexpect's ptyspawnall run children successfully in the same image — they usevfork()/fork()+exec. - The same GNU make, rebuilt with
./configure --disable-posix-spawn(which compiles make's alternatevfork()+execvp()job path instead of theposix_spawnone —job.c, guarded onUSE_POSIX_SPAWN), runs every recipe correctly on the identical runtime. A/B verified in the browser: the posix_spawn build fails all recipe cases with ENOSYS; the vfork build passes them all.
So fork/vfork/execve are wired; posix_spawn (glibc →
clone(CLONE_VM|CLONE_VFORK)) is not.
Impact
Any package that defaults to posix_spawn to launch children hits this wall
(make is the first we have shipped that does). The per-package workaround is to
force the fork path where the upstream offers a knob (make: --disable-posix-spawn),
but that only exists package-by-package — wiring posix_spawn's clone variant
in the syscall layer would fix the class.
Workaround in place (make)
We ship make built with --disable-posix-spawn so it uses vfork() + exec.
This is a recipe-level workaround on our side; it does not need a kernel change to
unblock make, but it does not generalise to other posix_spawn users, which is
why this is filed.
No distro submodule pins moved — this is a runtime/syscall-layer report, not a component version bump.