[Development] Deprecating the static QProcess::startDetached() overloads
Thiago Macieira
thiago.macieira at intel.com
Wed Feb 27 22:47:46 CET 2019
On Wednesday, 27 February 2019 12:22:05 PST Thiago Macieira wrote:
> Good point: so long as the parent process is still running, it MUST
> waitpid() on the child processes. So even if we make QProcess front-end
> abandon the child, the backend in forkfd must still know about it.
>
> When the parent process exits, the children will be reparented to PID 1. But
> their controlling TTYs, process groups and session IDs will not change. We
> can assume you properly redirected std{in,out,err} away from the TTYs if
> you meant to detach, but we need to know whether to detach the controlling
> TTY too (if any), otherwise the process will get a SIGHUP when the TTY
> itself gets closed. As for PGRP and SID, I don't remember those Unix arcana
> details to predict what would happen.
I've just realised that my alternative implementation of forkfd that
implements the double-forking for all processes could be handy here. For every
child that you start, it starts an intermediary babysitter process whose only
job is to waitpid() on the child. I implemented this because this babysitter
process is not running alongside third party library code that could interfere
with the SIGCHLD signal handler.
However, it has serious drawbacks, so I don't think we should use it:
1) it creates one extra process per child, which lowers the number of
concurrent children you can have by half;
2) it's Linux-only, since I can't use fork() due to deadlocks. It uses
syscall(SYS_clone, ...) directly. And since it can't allocate memory due to
the same deadlocks, it needs to use syscall(SYS_getdents64) to list open files
in /proc/self/fd.
3) the babysitter process does not know when the parent exits, so it will keep
running and keep the entire set of libraries of the Qt parent application
loaded in memory for as long as the child process is running.
3.bis) as a result of (3), it will cause COW in any memory written to by the
parent process.
I implemented this because, unlike the current solution, if you pass the
forkfd pipe to another process and exit, the receiving process will still be
able to get the exit notification, as the kernel implementation intended to
do.
(3) can be mitigated polling on the outgoing pipe, which allows us to find out
if all the reading ends have closed, then exit the babysitter process. That
won't solve (3.bis) nor will it solve the case where the parent execve()s a
smaller executable. To do that, we'd need to go deeper into Linux-only and
unmap any other memory regions we didn't need, and switch to an alternate
stack.
To remove the Linux-only dependency, the only solution I can think of is to
use a libexec executable, but that has a startup cost of its own. And nothing
solves (1).
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel System Software Products
More information about the Development
mailing list