forkfd: don't attempt to guess EWOULDBLOCK when WNOHANG is active

Reading the kernel sources, I was sure we'd get an ECHILD if the child
hadn't exited yet, but that's not the case. We only get ECHILD if the
current process has no child processes. But if we do have one and the
one we're waiting for hasn't exited, waitid() returns 0.

So let's not attempt to correct it with forkfd_wait() or forkfd_wait4().
Those have "wait" in the name, so they should behave exactly the same
way. The man pages say:

 waitpid(): if WNOHANG was specified and one or more child(ren)
       specified by pid exist, but have not yet changed state, then 0 is
       returned.
 waitid(): returns 0 on success or if WNOHANG was specified and no
       child(ren) specified by id has yet changed state

This was found while studying QTBUG-100174.

QProcess does not use this code path (blocking mode forkfd only).
Matching OpenDCDiag PR:
https://github.com/opendcdiag/opendcdiag/pull/62

Pick-to: 6.2 6.3
Change-Id: Ibf4acec0f166495998f7fffd16d6de6853a6e5a8
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Thiago Macieira 2022-02-24 16:00:53 -08:00
parent 15ac809c99
commit c4d78703e0
1 changed files with 2 additions and 3 deletions

View File

@ -184,10 +184,9 @@ int system_forkfd_wait(int ffd, struct forkfd_info *info, int ffdoptions, struct
options |= WNOHANG;
}
si.si_status = si.si_code = 0;
ret = sys_waitid(P_PIDFD, ffd, &si, options, rusage);
if (ret == -1 && errno == ECHILD) {
errno = EWOULDBLOCK;
} else if (ret == 0 && info) {
if (info) {
info->code = si.si_code;
info->status = si.si_status;
}