summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/forkfd
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2020-02-17 11:41:16 -0800
committerEdward Welbourne <eddy@chaos.org.uk>2020-03-25 20:19:38 +0100
commitdefd49f7bfa07395a2f2a69e2f9db94b8ac5d64c (patch)
treec146fc628492cf0619a82a21767831b5ba6a71c8 /src/3rdparty/forkfd
parentba5e2ce49a43c7d68e2ffa57b9e7f8d5d7fafe2f (diff)
forkfd: add FFD_VFORK_SEMANTICS flag
This flag asks forkfd() to use vfork semantics wherever available. That is, suspend the calling process execution until the child either does an execve(2) or _exit(2). The advantage of that is that it puts lower pressure on the OS VMM system, as the number of pages that need to be copy-on-write duplicated is much smaller (still not zero, as at least the stack in the child will be written to). However, the only implementation that supports using this flag for now is Linux's pidfd. It would be possible to add to FreeBSD, but pdfork(2) does not have a flag for this behavior -- if it gets one, we can add support for it later. Everywhere else, we need to force the child to not exit until we store the child process's PID in the ProcessInfo structure we allocated, which means the parent process must run before we even return from forkfd(). Change-Id: I1bee3bc466a04f19bd6efffd15f447f28c201aa9 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/3rdparty/forkfd')
-rw-r--r--src/3rdparty/forkfd/forkfd.c8
-rw-r--r--src/3rdparty/forkfd/forkfd.h7
-rw-r--r--src/3rdparty/forkfd/forkfd_linux.c5
3 files changed, 15 insertions, 5 deletions
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;