summaryrefslogtreecommitdiffstats
path: root/src/3rdparty
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2020-02-21 20:40:35 -0800
committerEdward Welbourne <eddy@chaos.org.uk>2020-03-25 20:19:36 +0100
commitba5e2ce49a43c7d68e2ffa57b9e7f8d5d7fafe2f (patch)
tree83bbffae2854711906011d41efe753525166de71 /src/3rdparty
parent4605583fec7b101057f72b0c8b967fcfac07e12d (diff)
forkfd: fix forkfd_wait when FFD_USE_FORK was active
If we detected that the OS supports a version of system forkfd (Linux pidfd, FreeBSD procdesc), the forkfd_wait() function was using only the system waiting implementation, which of course can't work for file descriptors created with FFD_USE_FORK. So just detect EBADF and attempt again. If the file descriptor is neither one of our pipes nor a system forkfd, bad things will happen... Fixes: QTBUG-82351 Change-Id: I4e559af2a9a1455ab770fffd15f59fb3160b22eb Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Diffstat (limited to 'src/3rdparty')
-rw-r--r--src/3rdparty/forkfd/forkfd.c28
1 files changed, 25 insertions, 3 deletions
diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c
index 795aa9dd68..80f0e448e6 100644
--- a/src/3rdparty/forkfd/forkfd.c
+++ b/src/3rdparty/forkfd/forkfd.c
@@ -29,6 +29,11 @@
#include "forkfd.h"
+/* Macros fine-tuning the build: */
+//#define FORKFD_NO_FORKFD 1 /* disable the forkfd() function */
+//#define FORKFD_NO_SPAWNFD 1 /* disable the spawnfd() function */
+//#define FORKFD_DISABLE_FORK_FALLBACK 1 /* disable falling back to fork() from system_forkfd() */
+
#include <sys/types.h>
#if defined(__OpenBSD__) || defined(__NetBSD__)
# include <sys/param.h>
@@ -96,6 +101,16 @@ static int system_has_forkfd(void);
static int system_forkfd(int flags, pid_t *ppid, int *system);
static int system_forkfd_wait(int ffd, struct forkfd_info *info, int ffdwoptions, struct rusage *rusage);
+static int disable_fork_fallback(void)
+{
+#ifdef FORKFD_DISABLE_FORK_FALLBACK
+ /* if there's no system forkfd, we have to use the fallback */
+ return system_has_forkfd();
+#else
+ return false;
+#endif
+}
+
#define CHILDREN_IN_SMALL_ARRAY 16
#define CHILDREN_IN_BIG_ARRAY 256
#define sizeofarray(array) (sizeof(array)/sizeof(array[0]))
@@ -629,9 +644,12 @@ int forkfd(int flags, pid_t *ppid)
int efd;
#endif
+ if (disable_fork_fallback())
+ flags &= ~FFD_USE_FORK;
+
if ((flags & FFD_USE_FORK) == 0) {
fd = system_forkfd(flags, ppid, &ret);
- if (ret)
+ if (ret || disable_fork_fallback())
return fd;
}
@@ -815,8 +833,12 @@ int forkfd_wait4(int ffd, struct forkfd_info *info, int options, struct rusage *
struct pipe_payload payload;
int ret;
- if (system_has_forkfd())
- return system_forkfd_wait(ffd, info, options, rusage);
+ if (system_has_forkfd()) {
+ /* if this is one of our pipes, not a procdesc/pidfd, we'll get an EBADF */
+ ret = system_forkfd_wait(ffd, info, options, rusage);
+ if (disable_fork_fallback() || ret != -1 || errno != EBADF)
+ return ret;
+ }
ret = read(ffd, &payload, sizeof(payload));
if (ret == -1)