Bug 30349 - Support returning a pidfd from posix_spawn()
Summary: Support returning a pidfd from posix_spawn()
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: unspecified
: P2 enhancement
Target Milestone: 2.39
Assignee: Adhemerval Zanella
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-04-13 19:36 UTC by Philip Withnall
Modified: 2023-09-05 16:17 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Philip Withnall 2023-04-13 19:36:27 UTC
pidfd allows a process to keep a race-free handle to a child process, avoiding the problem of PID recycling meaning that a pid_t no longer refers to the process you thought it did.

We’d like to be able to use pidfds in GLib for race-free signalling of subprocesses. GLib currently uses posix_spawn() to spawn those subprocesses, though, and it cannot return a pidfd.

Could glibc please add a variant of posix_spawn() which returns a pidfd to the caller? I don’t know of the best API for this, but it could either be a new posix_spawn_with_pidfd() function, or be the existing posix_spawn() but somehow return a pidfd via a posix_spawnattr_t.
Comment 1 Philip Withnall 2023-04-13 19:37:00 UTC
Relevant discussion in GLib’s issue tracker: https://gitlab.gnome.org/GNOME/glib/-/issues/1866
Comment 2 Adhemerval Zanella 2023-04-13 20:16:07 UTC
I think it should be a reasonable interface for Linux.  I think the most straightforward interface would be:
 
 int posix_spawn_pidfd_ex (int *restrict pidfd, const char *restrict path,
                           const posix_spawn_file_actions_t *restrict file_actions,
                           const posix_spawnattr_t *restrict attrp,
                           char *const argv[restrict_arr],
                           char *const envp[restrict_arr])

Since returning the value on posix_spawnattr_t would require removing the const from it, which is not orthogonal to posix_spawn/posix_spawnp.

It will only work on Linux 5.2; but since it is an extension I think it should reasonable.
Comment 3 Adhemerval Zanella 2023-04-13 21:00:48 UTC
Another question is if would make sense to also provide the posix_spawnp variant as well, to be orthogonal to POSIX interface.
Comment 4 Adhemerval Zanella 2023-04-14 13:25:57 UTC
Another issue is if the new interface would be required to also return the pid_t from he spawned process.  Returning it would allow it to work with the default wait interfaces (waitpid, etc.); and it would avoid the possible issue of using this interface with a kernel between 5.2 and 5.4 (since waitid only support for 5.4+).

My take is to not support return the pid_t (since posix_spawn{p} already provides it), but now that we don't effoce kernel versions I don't have a good solution for the case kernel does not support waitid (P_PIDFD).
Comment 5 Adhemerval Zanella 2023-04-14 15:00:39 UTC
Another corner case, stressed by tst-spawn3.c, is when the process has already reached its maximum number of file descriptors (RLIMIT_NOFILE). Without pidfd, posix_spawn would create the process, while now clone (CLONE_PIDFD) fails.

It is expected, but it might be a caveat while using the interface.
Comment 6 Adhemerval Zanella 2023-04-14 15:02:58 UTC
(In reply to Adhemerval Zanella from comment #2)
> I think it should be a reasonable interface for Linux.  I think the most
> straightforward interface would be:
>  
>  int posix_spawn_pidfd_ex (int *restrict pidfd, const char *restrict path,
>                            const posix_spawn_file_actions_t *restrict
> file_actions,
>                            const posix_spawnattr_t *restrict attrp,
>                            char *const argv[restrict_arr],
>                            char *const envp[restrict_arr])

Another option, which would not require adding a new symbol, would to add a new posix_spawnattr_t attribute (POSIX_SPAWN_PIDFD), which would make posix_spawn return the pidfd on the 'pid' argument.  It should be safe at least on Linux, where pid_t and int are interchangeable.
Comment 7 Adhemerval Zanella 2023-04-18 17:59:19 UTC
After discussion with other maintainers, it seems that it would be better not to reuse the posix_spawn and posix_spawnp interface (with a new flag) and instead add different interfaces.  Florian has raised the possible issue with language bindings that might track the argument lifetime and mixing pid_t and file descriptors might generate some problems in such scenarios.

And since we already provide wrappers over the Linux pidfd syscall, Florian also suggested using the same name convention.  The proposed interfaces are:

extern int pidfd_spawn (int *__restrict __pid,
                        const char *__restrict __path,
                        const posix_spawn_file_actions_t *__restrict __facts,
                        const posix_spawnattr_t *__restrict __attrp,
                        char *const __argv[__restrict_arr],
                        char *const __envp[__restrict_arr])
    __nonnull ((2, 5));

extern int pidfd_spawnp (int *__restrict __pid,
                         const char *__restrict __path,
                         const posix_spawn_file_actions_t *__restrict __facts,
                         const posix_spawnattr_t *__restrict __attrp,
                         char *const __argv[__restrict_arr],
                         char *const __envp[__restrict_arr])
    __nonnull ((2, 5));

I decided to reuse the posix_spawn attribute and file actions to avoid either to rehash posix_spawn API or add a new one.  This new API will be provided by spawn.h.
Comment 8 Adhemerval Zanella 2023-04-18 21:38:54 UTC
Proposed patch sent upstream - https://patchwork.sourceware.org/project/glibc/list/?series=19063
Comment 9 Philip Withnall 2023-05-15 17:01:57 UTC
I’ve looked over the latest patches in https://patchwork.sourceware.org/project/glibc/list/?series=19143, and it all looks good to me! I focused on looking at whether it would cover GLib’s needs, and whether the new API made sense and felt natural and complete. I have not done a line-by-line review or looked in detail at the /proc parsing code.

So, from the point of view of GLib, the proposed APIs look great. Thanks a lot for working on them.
Comment 10 Luca Boccassi 2023-08-28 12:22:35 UTC
The new API looks great also from systemd's point of view, thanks for your work, looking forward to using these!
Comment 11 Adhemerval Zanella 2023-09-05 16:10:25 UTC
Implemented on 2.39 (0d6f9f626521678f330f8bfee89e1cdb7e2b1062) by pidfd_spawn/pidfd_spawnp.
Comment 12 Philip Withnall 2023-09-05 16:17:52 UTC
Fantastic! Thanks for your work on this.