1 /*
2 * Check SIGCHLD siginfo_t decoding.
3 *
4 * Copyright (c) 2015-2018 Dmitry V. Levin <ldv@strace.io>
5 * Copyright (c) 2016-2022 The strace developers.
6 * All rights reserved.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "tests.h"
12 #include <assert.h>
13 #include <signal.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <sys/wait.h>
17
18 #include "time_enjoyment.h"
19
20 enum {
21 CPUTIME_LIMIT_NSEC = 100000000,
22 };
23
24 static siginfo_t sinfo;
25
26 static void
27 handler(int no, siginfo_t *si, void *uc)
28 {
29 memcpy(&sinfo, si, sizeof(sinfo));
30 }
31
32 int
33 main(void)
34 {
35 char utime_str[64];
36 char stime_str[64];
37
38 tprintf("%s", "");
39
40 int fds[2];
41 if (pipe(fds))
42 perror_msg_and_fail("pipe");
43
44 pid_t pid = fork();
45 if (pid < 0)
46 perror_msg_and_fail("fork");
47
48 if (!pid) {
49 char c;
50 (void) close(1);
51 assert(read(0, &c, sizeof(c)) == 1);
52 return 42;
53 }
54
55 (void) close(0);
56
57 struct sigaction sa = {
58 .sa_sigaction = handler,
59 .sa_flags = SA_SIGINFO
60 };
61 assert(sigaction(SIGCHLD, &sa, NULL) == 0);
62
63 sigset_t block_mask, unblock_mask;
64 assert(sigprocmask(SIG_SETMASK, NULL, &block_mask) == 0);
65 sigaddset(&block_mask, SIGCHLD);
66 assert(sigprocmask(SIG_SETMASK, &block_mask, NULL) == 0);
67
68 unblock_mask = block_mask;
69 sigdelset(&unblock_mask, SIGCHLD);
70
71 assert(write(1, "", 1) == 1);
72 (void) close(1);
73
74 sigsuspend(&unblock_mask);
75 tprintf("--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED"
76 ", si_pid=%d, si_uid=%d, si_status=%d"
77 ", si_utime=%s, si_stime=%s} ---\n",
78 sinfo.si_pid, sinfo.si_uid, sinfo.si_status,
79 clock_t_str(zero_extend_signed_to_ull(sinfo.si_utime),
80 ARRSZ_PAIR(utime_str)),
81 clock_t_str(zero_extend_signed_to_ull(sinfo.si_stime),
82 ARRSZ_PAIR(stime_str)));
83
84 int s;
85 assert(wait(&s) == pid);
86 assert(WIFEXITED(s) && WEXITSTATUS(s) == 42);
87
88 if (pipe(fds))
89 perror_msg_and_fail("pipe");
90 pid = fork();
91 if (pid < 0)
92 perror_msg_and_fail("fork");
93
94 if (!pid) {
95 (void) close(1);
96 char c;
97 assert(read(0, &c, sizeof(c)) == 1);
98 enjoy_time(CPUTIME_LIMIT_NSEC);
99 (void) raise(SIGUSR1);
100 return 1;
101 }
102
103 (void) close(0);
104
105 assert(write(1, "", 1) == 1);
106 (void) close(1);
107
108 sigsuspend(&unblock_mask);
109 tprintf("--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED"
110 ", si_pid=%d, si_uid=%d, si_status=SIGUSR1"
111 ", si_utime=%s, si_stime=%s} ---\n",
112 sinfo.si_pid, sinfo.si_uid,
113 clock_t_str(zero_extend_signed_to_ull(sinfo.si_utime),
114 ARRSZ_PAIR(utime_str)),
115 clock_t_str(zero_extend_signed_to_ull(sinfo.si_stime),
116 ARRSZ_PAIR(stime_str)));
117
118 assert(wait(&s) == pid);
119 assert(WIFSIGNALED(s) && WTERMSIG(s) == SIGUSR1);
120
121 if (pipe(fds))
122 perror_msg_and_fail("pipe");
123 pid = fork();
124 if (pid < 0)
125 perror_msg_and_fail("fork");
126
127 if (!pid) {
128 (void) close(1);
129 enjoy_time(CPUTIME_LIMIT_NSEC);
130 raise(SIGSTOP);
131 char c;
132 assert(read(0, &c, sizeof(c)) == 1);
133 return 0;
134 }
135
136 (void) close(0);
137
138 sigsuspend(&unblock_mask);
139 tprintf("--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_STOPPED"
140 ", si_pid=%d, si_uid=%d, si_status=SIGSTOP"
141 ", si_utime=%s, si_stime=%s} ---\n",
142 sinfo.si_pid, sinfo.si_uid,
143 clock_t_str(zero_extend_signed_to_ull(sinfo.si_utime),
144 ARRSZ_PAIR(utime_str)),
145 clock_t_str(zero_extend_signed_to_ull(sinfo.si_stime),
146 ARRSZ_PAIR(stime_str)));
147
148 assert(kill(pid, SIGCONT) == 0);
149
150 sigsuspend(&unblock_mask);
151 tprintf("--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_CONTINUED"
152 ", si_pid=%d, si_uid=%d, si_status=SIGCONT"
153 ", si_utime=%s, si_stime=%s} ---\n",
154 sinfo.si_pid, sinfo.si_uid,
155 clock_t_str(zero_extend_signed_to_ull(sinfo.si_utime),
156 ARRSZ_PAIR(utime_str)),
157 clock_t_str(zero_extend_signed_to_ull(sinfo.si_stime),
158 ARRSZ_PAIR(stime_str)));
159
160 assert(write(1, "", 1) == 1);
161 (void) close(1);
162
163 sigsuspend(&unblock_mask);
164 tprintf("--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED"
165 ", si_pid=%d, si_uid=%d, si_status=0"
166 ", si_utime=%s, si_stime=%s} ---\n",
167 sinfo.si_pid, sinfo.si_uid,
168 clock_t_str(zero_extend_signed_to_ull(sinfo.si_utime),
169 ARRSZ_PAIR(utime_str)),
170 clock_t_str(zero_extend_signed_to_ull(sinfo.si_stime),
171 ARRSZ_PAIR(stime_str)));
172
173 assert(wait(&s) == pid && s == 0);
174
175 tprintf("%s\n", "+++ exited with 0 +++");
176 return 0;
177 }