brintos

brintos / linux public Read only

0
0

wasm32: posix_spawn() ENOSYS (clone CLONE_VM|CLONE_VFORK unwired) while vfork()+exec works -> GNU make recipes "Function not implemented" #14

Open alex opened this issue · 0 comments
A alex commented

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, and expect's pty spawn all run children successfully in the same image — they use vfork()/fork() + exec.
  • The same GNU make, rebuilt with ./configure --disable-posix-spawn (which compiles make's alternate vfork() + execvp() job path instead of the posix_spawn one — job.c, guarded on USE_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.