diff options
Diffstat (limited to 'sysdeps/unix')
-rw-r--r-- | sysdeps/unix/sysv/linux/kernel-features.h | 6 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/syscalls.list | 1 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/wait4.c | 84 |
3 files changed, 90 insertions, 1 deletions
diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h index e6be76ff46..43faaa3f9d 100644 --- a/sysdeps/unix/sysv/linux/kernel-features.h +++ b/sysdeps/unix/sysv/linux/kernel-features.h @@ -208,4 +208,10 @@ # define __ASSUME_TIME64_SYSCALLS 1 #endif +/* Linux waitid prior kernel 5.4 does not support waiting for the current + process group. */ +#if __LINUX_KERNEL_VERSION >= 0x050400 +# define __ASSUME_WAITID_PID0_P_PGID +#endif + #endif /* kernel-features.h */ diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list index 603e517ca6..5f1352ad43 100644 --- a/sysdeps/unix/sysv/linux/syscalls.list +++ b/sysdeps/unix/sysv/linux/syscalls.list @@ -67,7 +67,6 @@ swapoff - swapoff i:s __swapoff swapoff unshare EXTRA unshare i:i unshare uselib EXTRA uselib i:s __compat_uselib uselib@GLIBC_2.0:GLIBC_2.23 utime - utime i:sP utime -wait4 - wait4 i:iWiP __wait4 wait4 chown - chown i:sii __libc_chown __chown chown diff --git a/sysdeps/unix/sysv/linux/wait4.c b/sysdeps/unix/sysv/linux/wait4.c new file mode 100644 index 0000000000..c97e212b54 --- /dev/null +++ b/sysdeps/unix/sysv/linux/wait4.c @@ -0,0 +1,84 @@ +/* Wait for process to change state. Linux version. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <sys/wait.h> +#include <sys/resource.h> +#include <sysdep-cancel.h> + +pid_t +__wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage) +{ +#ifdef __NR_wait4 + return SYSCALL_CANCEL (wait4, pid, stat_loc, options, usage); +#elif defined (__ASSUME_WAITID_PID0_P_PGID) + idtype_t idtype = P_PID; + + if (pid < -1) + { + idtype = P_PGID; + pid *= -1; + } + else if (pid == -1) + idtype = P_ALL; + else if (pid == 0) + idtype = P_PGID; + + options |= WEXITED; + + siginfo_t infop; + if (SYSCALL_CANCEL (waitid, idtype, pid, &infop, options, usage) < 0) + return -1; + + if (stat_loc) + { + switch (infop.si_code) + { + case CLD_EXITED: + *stat_loc = W_EXITCODE (infop.si_status, 0); + break; + case CLD_DUMPED: + *stat_loc = WCOREFLAG | infop.si_status; + break; + case CLD_KILLED: + *stat_loc = infop.si_status; + break; + case CLD_TRAPPED: + case CLD_STOPPED: + *stat_loc = W_STOPCODE (infop.si_status); + break; + case CLD_CONTINUED: + *stat_loc = __W_CONTINUED; + break; + default: + *stat_loc = 0; + break; + } + } + + return infop.si_pid; +# else +/* Linux waitid prior kernel 5.4 does not support waiting for the current + process. It is possible to emulate wait4 it by calling getpgid for + PID 0, however, it would require an additional syscall and it is inherent + racy: after the current process group is received and before it is passed + to waitid a signal could arrive causing the current process group to + change. */ +# error "The kernel ABI does not provide a way to implement wait4" +#endif +} +weak_alias (__wait4, wait4) |