1 /*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program 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
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /*
21 * NAME
22 * waitpid05.c
23 *
24 * DESCRIPTION
25 * Check that when a child kills itself with a kill statement after
26 * determining its process id by using getpid, the parent receives a
27 * correct report of the cause of its death. This also indirectly
28 * checks that getpid returns the correct process id.
29 *
30 * ALGORITHM
31 * For signals 1 - 15: fork a child that determines it's own process
32 * id, then sends the signal to itself. The parent waits to see if the
33 * demise of the child results in the signal number being returned to
34 * the parent.
35 *
36 * USAGE: <for command-line>
37 * waitpid05 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
38 * where, -c n : Run n copies concurrently.
39 * -e : Turn on errno logging.
40 * -i n : Execute test n times.
41 * -I x : Execute test for x seconds.
42 * -P x : Pause for x seconds between iterations.
43 * -t : Turn on syscall timing.
44 *
45 * History
46 * 07/2001 John George
47 * -Ported
48 * 04/2002 wjhuie sigset cleanups
49 *
50 * Restrictions
51 * None
52 */
53
54 #include <sys/file.h>
55 #include <sys/signal.h>
56 #include <sys/types.h>
57 #include <sys/wait.h>
58 #include <sys/time.h>
59 #include <sys/resource.h>
60 #include <unistd.h>
61 #include <errno.h>
62 #include "test.h"
63
64 static void do_child(int);
65 static void setup(void);
66 static void cleanup(void);
67
68 char *TCID = "waitpid05";
69 int TST_TOTAL = 1;
70
71 #ifdef UCLINUX
72 static void do_child_uclinux(void);
73 static int sig_uclinux;
74 #endif
75
main(int ac,char ** av)76 int main(int ac, char **av)
77 {
78 int pid, npid, sig, nsig;
79 int exno, nexno, status;
80 int lc;
81
82 tst_parse_opts(ac, av, NULL, NULL);
83
84 #ifdef UCLINUX
85 maybe_run_child(&do_child_uclinux, "d", &sig_uclinux);
86 #endif
87
88 setup();
89
90 /* check for looping state if -i option is given */
91 for (lc = 0; TEST_LOOPING(lc); lc++) {
92 /* reset tst_count in case we are looping */
93 tst_count = 0;
94
95 /*
96 * Set SIGTERM to SIG_DFL as test driver sets up to ignore
97 * SIGTERM
98 */
99 if (signal(SIGTERM, SIG_DFL) == SIG_ERR) {
100 tst_resm(TFAIL, "Sigset SIGTERM failed, errno = %d",
101 errno);
102
103 }
104
105 exno = 1;
106 for (sig = 1; sig <= 15; sig++) {
107 if (sig == SIGUSR1 || sig == SIGUSR2 || sig == SIGBUS)
108 continue;
109
110 /*Initialize signal to its default action */
111 signal(sig, SIG_DFL);
112 pid = FORK_OR_VFORK();
113
114 if (pid == 0) {
115 #ifdef UCLINUX
116 self_exec(av[0], "d", sig);
117 /* No fork() error check is done so don't */
118 /* do an error check here */
119 #else
120 do_child(sig);
121 #endif
122 } else {
123 errno = 0;
124 while (((npid = waitpid(pid, &status, 0)) !=
125 -1) || (errno == EINTR)) {
126 if (errno == EINTR)
127 continue;
128
129 if (npid != pid) {
130 tst_resm(TFAIL, "waitpid "
131 "error: unexpected "
132 "pid returned");
133 } else {
134 tst_resm(TPASS, "received "
135 "expected pid.");
136 }
137
138 nsig = status % 256;
139
140 /*
141 * to check if the core dump bit has
142 * been set, bit #7
143 */
144 if (nsig >= 128) {
145 nsig -= 128;
146 if ((sig == 1) || (sig == 2) ||
147 (sig == 9) || (sig == 13) ||
148 (sig == 14) ||
149 (sig == 15)) {
150 tst_resm(TFAIL,
151 "signal "
152 "error : "
153 "core dump "
154 "bit set for"
155 " exception "
156 "number %d",
157 sig);
158 }
159 } else if ((sig == 3) || (sig == 4) ||
160 (sig == 5) || (sig == 6) ||
161 (sig == 8) || (sig == 11)) {
162 tst_resm(TFAIL,
163 "signal error: "
164 "core dump bit not "
165 "set for exception "
166 "number %d", sig);
167 }
168
169 /*
170 * nsig is the signal number returned
171 * by waitpid
172 */
173 if (nsig != sig) {
174 tst_resm(TFAIL, "waitpid "
175 "error: unexpected "
176 "signal returned");
177 tst_resm(TINFO, "got signal "
178 "%d, expected "
179 "%d", nsig, sig);
180 }
181
182 /*
183 * nexno is the exit number returned
184 * by waitpid
185 */
186 nexno = status / 256;
187 if (nexno != 0) {
188 tst_resm(TFAIL, "signal "
189 "error: unexpected "
190 "exit number "
191 "returned");
192 } else {
193 tst_resm(TPASS, "received "
194 "expected exit number.");
195 }
196 }
197 }
198 }
199
200 if (access("core", F_OK) == 0)
201 unlink("core");
202 }
203
204 cleanup();
205 tst_exit();
206 }
207
do_child(int sig)208 static void do_child(int sig)
209 {
210 int exno = 1;
211 int pid = getpid();
212
213 if (kill(pid, sig) == -1) {
214 tst_resm(TFAIL, "kill error: kill unsuccessful");
215 exit(exno);
216 }
217 }
218
219 #ifdef UCLINUX
220 /*
221 * do_child_uclinux()
222 * run do_child with the appropriate sig variable
223 */
do_child_uclinux(void)224 static void do_child_uclinux(void)
225 {
226 do_child(sig_uclinux);
227 }
228 #endif
229
setup(void)230 static void setup(void)
231 {
232 struct rlimit newlimit;
233
234 TEST_PAUSE;
235
236 tst_tmpdir();
237
238 newlimit.rlim_max = newlimit.rlim_cur = RLIM_INFINITY;
239 if (setrlimit(RLIMIT_CORE, &newlimit) != 0)
240 tst_resm(TWARN,
241 "setrlimit(RLIMIT_CORE,RLIM_INFINITY) failed; this may cause some false core-dump test failures");
242 }
243
cleanup(void)244 static void cleanup(void)
245 {
246 tst_rmdir();
247 }
248