newsgnulib - GNU portability library - News


Gnulib helps you get away from fork() + exec()

Item posted by Bruno Haible <haible> on Sun 20 Nov 2022 04:27:43 PM UTC.

Spawning a new process has traditionally been coded by a fork() call, followed by an execv/execl/execlp/execvp call in the child process. This is often referred to as the fork + exec idiom.

In 90% of the cases, there is something better: the posix_spawn/posix_spawnp functions.

Why is that better?

First, it's faster. The glibc implementation of posix_spawn, on Linux, uses a specialized system call (clone3) with a custom child-process stack, that makes it outperform the fork + exec idiom already now. And another speedup of 30% is being considered, see .

Second, it's more portable. While most Unix-like operating systems nowadays have both fork and posix_spawn, there are platforms which don't have fork(), namely Windows (excluding Cygwin). Comes in Gnulib for portability: Gnulib provides a posix_spawn implementation not only for the Unix platforms which lack it (today, that's only HP-UX), but also for Windows. In fact, Gnulib's posix_spawn implementation is the world's first for Windows platforms; the mingw libraries don't have one.

Why only in 90% of the cases?

Typically, between the fork and exec part, the application code will set up or configure some things in the child process. Such as closing file descriptors (this is necessary when pipes are involved), changing the current directory, and things like that.

posix_spawn has a certain set of setup / configuration "actions" that are supported. Namely, searching for the program in $PATH, opening files, shuffling arounds or closing file descriptors, and setting the tty-related process group. If that's all that the application code needs, then posix_spawn fits the bill. That should be 90% of the cases in practice.

How to do the change?

Before you replace a bit of fork + exec code with posix_spawn, you need to understand the main difference: The setup / configuration "actions" are encoded as C system calls in the old approach. Whereas with posix_spawn they are specified declaratively, by constructing an "actions" object in memory.

When you have done this change, you would test it on a glibc system.

And finally, for portability, import the Gnulib modules corresponding to all the posix_spawn* functions that you need.

Back to the top

Powered by Savane 3.13-4b48.
Corresponding source code