summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/forkfd/forkfd.h
Commit message (Collapse)AuthorAgeFilesLines
* forkfd: implement vfork(2)-like support on LinuxThiago Macieira2022-07-161-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | fork() works by implementing Copy-On-Write for all pages that either the parent or the child process write to. So if the parent process continues running while the child is between fork(2) and execve(2), then it will keep causing page faults and requiring the OS to duplicate those pages, which may be expensive (page table updates, TLB flushes, etc.). This problem is aggravated if the parent process is multithreaded, as the simple act of running in the parent will cause those threads' stacks to cause page faults. The BSD solution for that was vfork(), which has two differences in behavior: (1) it blocks the parent from running and (2) it shares memory with it. But it's always been tricky, so POSIX.1-2001 deprecated it and 2008 removed its definition completely. Still, it is available somewhat widely, and on Linux that can be achieved with clone(2) and the CLONE_VFORK and CLONE_VM flags, for those two behaviors respectively. Because of (2), we can't return from the forkfd() function in the child (as that would trash the stack in the parent process), so to implement this functionality vforkfd() adds a callback of the same signature as glibc's clone(2) wrapper (something that hadn't occurred to me when we attempted to use CLONE_VFORK last time). On Linux, (1) is no problem, as clone(2) has native forkfd support. But on other OSes, forkfd() requires the parent to run before the child execve()s, in order to save the child PID in the list of children we're going to handle SIGCHLD for in a non-racy way. Investigating if it is possible to use vfork() anyway is left as an exercise for the reader. Matching OpenDCDiag pull request: https://github.com/opendcdiag/opendcdiag/pull/94 Pick-to: 6.4 Fixes: QTBUG-104493 Change-Id: Id0fb9ab0089845ee8843fffd16fa63c7c6f7dd1c Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Milian Wolff <milian.wolff@kdab.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* forkfd: remove FFD_VFORK_SEMANTICSThiago Macieira2020-06-301-1/+0
| | | | | | | | | | | | | | | This will never work, not unless libc implements it themselves, since the child process is not allowed to return from the function that does the vfork(), as subsequent use of the stack would trash the frozen parent's return address, and in our case that's syscall(). Instead, we may add a vforkfd() function that takes a callback function that will be called in that context, like the glibc clone(3) wrapper does. Pick-to: 5.15 Change-Id: I1dba29bc0f454df09ca1fffd161800b453c00593 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* forkfd: add FFD_VFORK_SEMANTICS flagThiago Macieira2020-03-251-3/+4
| | | | | | | | | | | | | | | | | | | | 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>
* forkfd: introduce forkfd_wait4() that takes optionsThiago Macieira2020-03-251-1/+8
| | | | | | | | | | | | | | | | | | "wait4" because it looks like the wait4() BSD function, which has the signature: pid_t wait4(pid_t pid, int *wstatus, int options, struct rusage *rusage); And because ours also has 4 parameters. Having options is important anyway. I might want to add some more later, but we can't really support them with the fall back implementation (in fact, we don't honor WNOHANG in the fall back implementation either). Change-Id: I4e559af2a9a1455ab770fffd15f5858bb357e15b Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
* forkfd: add FFD_USE_FORK to force use of fork()Thiago Macieira2020-01-091-2/+3
| | | | | Change-Id: Ia2aa807ffa8a4c798425fffd15d933e47919247a Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
* forkfd: fix compilation in C mode without precompiled headersThiago Macieira2019-08-201-2/+3
| | | | | | | | | Missing one "struct" and one #include <sys/wait.h> for struct rusage. Change-Id: Iec9c051acd73484c8d94fffd15b9a1274703afca Reviewed-by: Marc Mutz <marc.mutz@kdab.com> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* Update the Intel copyright yearThiago Macieira2016-01-211-1/+1
| | | | | | | | | Not that we require it, but since The Qt Company did it for all files they have copyright, even if they haven't touched the file in years (especially not in 2016), I'm doing the same. Change-Id: I7a9e11d7b64a4cc78e24ffff142b4c9d53039846 Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
* forkfd: fix _POSIX_SPAWN feature checkLouai Al-Khanji2015-09-041-2/+2
| | | | | Change-Id: Ia44edbac3a1bd2da92ee8c92956abfe49d8763b8 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* forkfd: update the API to add a reading and closing functionThiago Macieira2015-07-171-1/+9
| | | | | | | | | | | | | | Right now the two functions being added are just wrappers, but this will allow us in the future to support FreeBSD and Linux's system calls that do the equivalent of forkfd, but have slightly different semantics in the actual getting of the information from the file descriptor. See-Also: https://lkml.org/lkml/2015/3/12/1044 See-Also: http://www.freebsd.org/cgi/man.cgi?query=pdfork Change-Id: Ia0aac2f09e9245339951ffff13c94acb5f4ff204 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> Reviewed-by: Rafael Roquetto <rafael.roquetto@kdab.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Relicense forkfd under an MIT licenseThiago Macieira2015-03-231-28/+15
| | | | | | | | | The difference between BSD and MIT is the need to reproduce the copyright in the documentation and the non-endorsement by a particular company (the name of which was stale in the forkfd code). Change-Id: Iee8cbc07c4434ce9b560ffff13cd0174934935e9 Reviewed-by: Rafael Roquetto <rafael.roquetto@kdab.com>
* Add spawnfd for use where fork / forkfd can't be usedThiago Macieira2015-01-231-0/+13
| | | | | | | | | | | | | | | | | | | | In certain environments, using fork() is not recommended due to the need for an MMU. This commit adds support for those environments, by using posix_spawn. Limitations of this environment are: - we cannot reliably detect failure to exec (e.g. non-existing executable) - we cannot do setsid(); we do setpgrp(0, 0) instead - we cannot thread-safely chdir() to the requested dir Because of the former limitation, the QProcess unit tests that rely on failure-to-start error conditions are either skipped or marked as expected failures. There's a non-reliable solution that is implemented in a another commit. This change also makes it easier to transition the QNX builds to using fork(), which is supported from QNX Neutrino 6.6 and onwards. Change-Id: I5cb46abf2ef8783941525d35cc991f00d2bf2d58 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Fix forkfd build when O_CLOEXEC isn't defined.Thiago Macieira2015-01-161-2/+2
| | | | | | | | | | | | | | | | | | O_CLOEXEC was introduced with the 2008 revision of POSIX.1 and it's the only way of doing child processes safely with fork(2) in multithreaded applications. But we need to support pre-2008 systems, so we can't use that constant. So let's just choose two arbitrary values for both of our constants -- we need to change both because we need to be sure that FFD_CLOEXEC won't be the same as FFD_NONBLOCK. Linux will probably implement them to the O_ constants, like epoll, signalfd and inotify have done. Change-Id: I20a5aa6e6264e7a219e19759eeb8747e01df05ff Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> Reviewed-by: Rafael Roquetto <rafael.roquetto@kdab.com>
* Import forkfd into qtbaseThiago Macieira2014-11-041-0/+58
forkfd is a tool that I designed to facilitate spawning sub-processes. It's implemented in C, not C++, so that it could be used by other libraries as well. To work in all platforms Qt supports and with all compilers Qt is known to work with, we'll need to replace the generic GCC atomics that are provided here. Change-Id: I0a6f86cc220a7c52c8d4284bb7140c56d5cf836a Reviewed-by: Rafael Roquetto <rafael.roquetto@kdab.com> Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>