1 | /* Wait for process to change state. Linux version. |
2 | Copyright (C) 2019-2021 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <sys/wait.h> |
20 | #include <sys/resource.h> |
21 | #include <sys/types.h> |
22 | #include <sysdep-cancel.h> |
23 | #include <tv32-compat.h> |
24 | |
25 | pid_t |
26 | __wait4_time64 (pid_t pid, int *stat_loc, int options, struct __rusage64 *usage) |
27 | { |
28 | #ifdef __NR_wait4 |
29 | # if __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 |
30 | return SYSCALL_CANCEL (wait4, pid, stat_loc, options, usage); |
31 | # else |
32 | pid_t ret; |
33 | struct __rusage32 usage32; |
34 | |
35 | ret = SYSCALL_CANCEL (wait4, pid, stat_loc, options, |
36 | usage != NULL ? &usage32 : NULL); |
37 | |
38 | if (ret > 0 && usage != NULL) |
39 | rusage32_to_rusage64 (&usage32, usage); |
40 | |
41 | return ret; |
42 | # endif |
43 | #elif defined (__ASSUME_WAITID_PID0_P_PGID) |
44 | idtype_t idtype = P_PID; |
45 | |
46 | if (pid < -1) |
47 | { |
48 | idtype = P_PGID; |
49 | pid *= -1; |
50 | } |
51 | else if (pid == -1) |
52 | idtype = P_ALL; |
53 | else if (pid == 0) |
54 | idtype = P_PGID; |
55 | |
56 | options |= WEXITED; |
57 | |
58 | siginfo_t infop; |
59 | |
60 | # if __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 |
61 | if (SYSCALL_CANCEL (waitid, idtype, pid, &infop, options, usage) < 0) |
62 | return -1; |
63 | # else |
64 | { |
65 | struct __rusage32 usage32; |
66 | if (SYSCALL_CANCEL (waitid, idtype, pid, &infop, options, &usage32) < 0) |
67 | return -1; |
68 | if (usage != NULL) |
69 | rusage32_to_rusage64 (&usage32, usage); |
70 | } |
71 | # endif |
72 | |
73 | if (stat_loc) |
74 | { |
75 | switch (infop.si_code) |
76 | { |
77 | case CLD_EXITED: |
78 | *stat_loc = W_EXITCODE (infop.si_status, 0); |
79 | break; |
80 | case CLD_DUMPED: |
81 | *stat_loc = WCOREFLAG | infop.si_status; |
82 | break; |
83 | case CLD_KILLED: |
84 | *stat_loc = infop.si_status; |
85 | break; |
86 | case CLD_TRAPPED: |
87 | case CLD_STOPPED: |
88 | *stat_loc = W_STOPCODE (infop.si_status); |
89 | break; |
90 | case CLD_CONTINUED: |
91 | *stat_loc = __W_CONTINUED; |
92 | break; |
93 | default: |
94 | *stat_loc = 0; |
95 | break; |
96 | } |
97 | } |
98 | |
99 | return infop.si_pid; |
100 | #else |
101 | /* Linux waitid prior kernel 5.4 does not support waiting for the current |
102 | process. It is possible to emulate wait4 it by calling getpgid for |
103 | PID 0, however, it would require an additional syscall and it is inherent |
104 | racy: after the current process group is received and before it is passed |
105 | to waitid a signal could arrive causing the current process group to |
106 | change. */ |
107 | # error "The kernel ABI does not provide a way to implement wait4" |
108 | #endif |
109 | } |
110 | |
111 | #if __TIMESIZE != 64 |
112 | libc_hidden_def (__wait4_time64) |
113 | |
114 | pid_t |
115 | __wait4 (pid_t pid, int *stat_loc, int options, struct rusage *usage) |
116 | { |
117 | pid_t ret; |
118 | struct __rusage64 usage64; |
119 | |
120 | ret = __wait4_time64 (pid, stat_loc, options, |
121 | usage != NULL ? &usage64 : NULL); |
122 | |
123 | if (ret > 0 && usage != 0) |
124 | rusage64_to_rusage (&usage64, usage); |
125 | |
126 | return ret; |
127 | } |
128 | #endif |
129 | libc_hidden_def (__wait4); |
130 | weak_alias (__wait4, wait4) |
131 | |