|
|
Subscribe / Log in / New account

Race-free process creation in the GNU C Library

Race-free process creation in the GNU C Library

Posted Sep 4, 2023 0:46 UTC (Mon) by njs (subscriber, #40338)
Parent article: Race-free process creation in the GNU C Library

There are some subtle details here that I think the article and underlying thread didn't quite fully understand, and it took me a minute to read the thread and figure out what was going on, so here's my current understanding:

As a few other comments noted, it's already possible for parents to avoid the race condition when spawning a child and getting a pidfd to it, because pids aren't recycled when the child dies – they're recycled after the parent affirmatively calls one of the wait variants to reap the exit status. So "just" call pidfd_open before you call wait, problem solved.

But this is still useful for a few reasons:

- "make sure nothing in your program calls wait, or else a very obscure issue could happen one time in a million" is certainly an invariant you *can* enforce, but it sure is easier and less error prone if you don't have to.

- if you're writing a reusable library, you don't know what other code will be running in the same process as you. You might prefer to be robust against being used by poorly implemented callers, that do things like call wait on everything.

- if you're writing a highly backwards compatible library you *can't* add undocumented, observable side effects to your operations, even if the only code that would notice is arguably broken. Corollary: right now these libraries cannot move existing functionality out into helper processes, even if this would be eg better for security, and even if the user-visible API stays exactly the same. If mylib_do_foo() starts secretly spawning a child, that fact can't be encapsulated, because it will leak out into the process-global child monitoring APIs like SIGCHLD and wait.

But, there's an even more obscure Linux feature that can solve this: if you pass exit_signal=0 to clone, then the child process is hidden from not just SIGCHLD but also wait (!). Technically I think this is orthogonal to the pidfd stuff, but they're very convenient to use together, so it makes sense that a new interface exposing exit_signal=0 would also return a pidfd instead of a pid.

... Unfortunately the proposed patch only adds support for this to fork(), not to posix_spawn(), and the fork() support is controversial in general. But hopefully it'll get revised so we end up with exit_signal=0 *and* pidfd support in posix_spawn.

(It would also be nice if you could arrange that a child with exit_signal=0 and CLONE_PIDFD would be automatically orphaned when the pidfd was closed, since regular SIGCHLD reaping won't work on it. But that would be a whole other kernel patch.)


to post comments


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds