diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2020-02-21 20:40:35 -0800 |
---|---|---|
committer | Edward Welbourne <eddy@chaos.org.uk> | 2020-03-25 20:19:36 +0100 |
commit | ba5e2ce49a43c7d68e2ffa57b9e7f8d5d7fafe2f (patch) | |
tree | 83bbffae2854711906011d41efe753525166de71 /src/3rdparty | |
parent | 4605583fec7b101057f72b0c8b967fcfac07e12d (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.c | 28 |
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) |