diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c index 80f0e448e6..50784deaa5 100644 --- a/src/3rdparty/forkfd/forkfd.c +++ b/src/3rdparty/forkfd/forkfd.c @@ -611,12 +611,18 @@ static int create_pipe(int filedes[], int flags) * descriptor. You probably want to set this flag, since forkfd() does not work * if the original parent process dies. * - * @li @C FFD_USE_FORK Tell forkfd() to actually call fork() instead of a + * @li @c FFD_USE_FORK Tell forkfd() to actually call fork() instead of a * different system implementation that may be available. On systems where a * different implementation is available, its behavior may differ from that of * fork(), such as not calling the functions registered with pthread_atfork(). * If that's necessary, pass this flag. * + * @li @c FFD_VFORK_SEMANTICS Tell forkfd() to use semantics similar to + * vfork(), if that's available. For example, on Linux with pidfd support + * available, this will add the CLONE_VFORK option. On most other systems, + * including Linux without pidfd support, this option does nothing, as using + * the actual vfork() system call would cause a race condition. + * * The file descriptor returned by forkfd() supports the following operations: * * @li read(2) When the child process exits, then the buffer supplied to diff --git a/src/3rdparty/forkfd/forkfd.h b/src/3rdparty/forkfd/forkfd.h index 205928cc2b..a864b59861 100644 --- a/src/3rdparty/forkfd/forkfd.h +++ b/src/3rdparty/forkfd/forkfd.h @@ -38,9 +38,10 @@ extern "C" { #endif -#define FFD_CLOEXEC 1 -#define FFD_NONBLOCK 2 -#define FFD_USE_FORK 4 +#define FFD_CLOEXEC 1 +#define FFD_NONBLOCK 2 +#define FFD_USE_FORK 4 +#define FFD_VFORK_SEMANTICS 8 #define FFD_CHILD_PROCESS (-2) diff --git a/src/3rdparty/forkfd/forkfd_linux.c b/src/3rdparty/forkfd/forkfd_linux.c index 87acdc3341..c4f723343f 100644 --- a/src/3rdparty/forkfd/forkfd_linux.c +++ b/src/3rdparty/forkfd/forkfd_linux.c @@ -147,7 +147,10 @@ int system_forkfd(int flags, pid_t *ppid, int *system) } *system = 1; - pid = sys_clone(CLONE_PIDFD, &pidfd); + unsigned long cloneflags = CLONE_PIDFD; + if (flags & FFD_VFORK_SEMANTICS) + cloneflags |= CLONE_VFORK; + pid = sys_clone(cloneflags, &pidfd); if (ppid) *ppid = pid;