Skip to content

Add support for spawning processes using posix_spawn() - #56

Open
guillerodriguez wants to merge 4 commits into
masterfrom
feat/posix-spawn
Open

Add support for spawning processes using posix_spawn()#56
guillerodriguez wants to merge 4 commits into
masterfrom
feat/posix-spawn

Conversation

@guillerodriguez

Copy link
Copy Markdown
Contributor

No description provided.

Move the child-side process spawning implementation to a separate
source file, so that it can later be reused by the spawn helper
in the forthcoming posix_spawn implementation.

Make sure all child-side functions called after fork() are static
and live in the same translation unit, so that calls between them
cannot be lazily bound (resolving a lazy binding runs the dynamic
linker, which can deadlock the child). The entry point itself
(cpproc_child_fork_exec) is called before fork(), so its binding
is resolved safely in the parent.

This commit introduces no functional changes.

Signed-off-by: Guillermo Rodríguez <grodriguez@ingelabs.com>
Spawning through fork() can be expensive when the parent process is
large. Add support for spawning using posix_spawn(), if available.

The portable posix_spawn() interface cannot perform the whole child
setup, though: there is no way to ask it to mark every remaining
descriptor close-on-exec or to run our existing PATH search. Execute
the target through a small helper program, cpspawnhelper, which reuses
the same child-side code as the fork path.

Invoke posix_spawn() without file actions or attributes, so that older
versions of glibc use vfork() instead of fork() internally. Pass the
descriptor numbers, the working directory, the parent's PATH and the
target arguments in the helper's argv.

Launch the helper with an empty environment to prevent the dynamic
linker from acting on the target's loader settings before main().
The target environment is sent through a dedicated pipe to keep it
out of the helper's command line.

The new posix_spawn-based mechanism is selected in VMProcess, but
it is disabled for now.

Signed-off-by: Guillermo Rodríguez <grodriguez@ingelabs.com>
POSIX allows posix_spawn() to report an exec failure in the child
only through an exit status of 127, with the call itself returning
success (glibc did this before 2.24; see glibc #18433). That status
cannot be distinguished from a successfully executed target that
later exits with 127. The helper can also die after its own exec
succeeds but before main() runs, for example if its dynamic loader
fails.

In either failure case, the parent would read EOF from the fail
pipe and report a successful spawn even though the target never ran.

Make the helper write a readiness marker to the fail pipe after
parsing its arguments, and require the parent to receive it before
treating a subsequent EOF as success. EOF without the marker now
reports an error instead of a successful spawn.

Signed-off-by: Guillermo Rodríguez <grodriguez@ingelabs.com>
Allow selecting the process spawning mechanism through the
gnu.lang.process.posixSpawn system property: "false" forces fork(),
any other value (including empty) forces posix_spawn(), and an
unset property selects the platform default.

Default to posix_spawn() on Linux and macOS, and to fork() on other
platforms, where the behavior of posix_spawn() has not been verified.

Signed-off-by: Guillermo Rodríguez <grodriguez@ingelabs.com>
@guillerodriguez
guillerodriguez requested a review from phvega August 11, 2026 11:07
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.

1 participant