LibWasm: Clear FD_CLOEXEC on shm fd before spawning Cranelift child

On macOS, the cranelift JIT compilation step works by creating an
anonymous shared memory segment via shm_open() in the parent process
and passing the fd as an argument to the spawned cranelift-compiler
child. POSIX requires shm_open() to set FD_CLOEXEC on the returned
fd, which caused the child to immediately fail with EBADF when it
tried to read from the inherited fd number.

Clear FD_CLOEXEC after shm_open() so the fd actually survives the
spawn. The Linux memfd_create() path is unaffected since we call it
with flags=0 (no MFD_CLOEXEC), and Windows passes an inheritable
HANDLE instead of an fd.
This commit is contained in:
Andreas Kling 2026-05-11 08:14:27 +02:00 committed by Andreas Kling
parent fc401bd830
commit c9e135cdff

View file

@ -912,6 +912,10 @@ static void try_cranelift_compile_batch(Vector<BatchInput>& batch)
if (fd < 0)
return;
shm_unlink(shm_name);
// POSIX shm_open sets FD_CLOEXEC on the returned fd, which would close it
// in the spawned cranelift-compiler child. Clear it so the child inherits.
if (auto flags = fcntl(fd, F_GETFD); flags >= 0)
fcntl(fd, F_SETFD, flags & ~FD_CLOEXEC);
ScopeGuard close_fd = [fd] { close(fd); };
if (ftruncate(fd, static_cast<off_t>(total_size)) < 0)
return;