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 *	waitpid02.c
23 *
24 * DESCRIPTION
25 *	Check that when a child gets killed by an integer zero
26 *	divide exception, the waiting parent is correctly notified.
27 *
28 * ALGORITHM
29 *	Fork a child and send a SIGFPE to it. The parent waits for the
30 *	death of the child and checks that SIGFPE was returned.
31 *
32 * USAGE:  <for command-line>
33 *      waitpid02 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
34 *      where,  -c n : Run n copies concurrently.
35 *              -e   : Turn on errno logging.
36 *              -i n : Execute test n times.
37 *              -I x : Execute test for x seconds.
38 *              -P x : Pause for x seconds between iterations.
39 *              -t   : Turn on syscall timing.
40 *
41 * History
42 *	07/2001 John George
43 *		-Ported
44 *	10/2002 Paul Larson
45 *		Div by zero doesn't cause SIGFPE on some archs, fixed
46 *		to send the signal with kill
47 *
48 * Restrictions
49 *	None
50 */
51
52#include <sys/file.h>
53#include <sys/resource.h>
54#include <sys/signal.h>
55#include <sys/types.h>
56#include <sys/wait.h>
57#include <errno.h>
58#include "test.h"
59
60static void do_child(void);
61static void setup(void);
62
63char *TCID = "waitpid02";
64int TST_TOTAL = 1;
65
66int main(int argc, char **argv)
67{
68	int lc;
69
70	int pid, npid, sig, nsig;
71	int nexno, status;
72
73	tst_parse_opts(argc, argv, NULL, NULL);
74#ifdef UCLINUX
75	maybe_run_child(&do_child, "");
76#endif
77
78	setup();
79
80	for (lc = 0; TEST_LOOPING(lc); lc++) {
81		tst_count = 0;
82
83		sig = SIGFPE;
84
85		pid = FORK_OR_VFORK();
86
87		if (pid < 0)
88			tst_brkm(TBROK|TERRNO, NULL, "fork failed");
89
90		if (pid == 0) {
91#ifdef UCLINUX
92			self_exec(argv[0], "");
93			/* No fork() error check is done so don't check here */
94#else
95			do_child();
96#endif
97		} else {
98			kill(pid, sig);
99			errno = 0;
100			while (((npid = waitpid(pid, &status, 0)) != -1) ||
101			       (errno == EINTR)) {
102				if (errno == EINTR)
103					continue;
104
105				if (npid != pid) {
106					tst_resm(TFAIL, "waitpid error: "
107						 "unexpected pid returned");
108				} else {
109					tst_resm(TPASS,
110						 "received expected pid");
111				}
112
113				nsig = WTERMSIG(status);
114
115				/*
116				 * nsig is the signal number returned by
117				 * waitpid
118				 */
119				if (nsig != sig) {
120					tst_resm(TFAIL, "waitpid error: "
121						 "unexpected signal returned");
122				} else {
123					tst_resm(TPASS, "received expected "
124						 "signal");
125				}
126
127				/*
128				 * nexno is the exit number returned by
129				 * waitpid
130				 */
131				nexno = WEXITSTATUS(status);
132				if (nexno != 0) {
133					tst_resm(TFAIL, "signal error: "
134						 "unexpected exit number "
135						 "returned");
136				} else {
137					tst_resm(TPASS, "received expected "
138						 "exit value");
139				}
140			}
141		}
142	}
143
144	tst_exit();
145}
146
147static void do_child(void)
148{
149	int exno = 1;
150
151	while (1)
152		usleep(10);
153
154	exit(exno);
155}
156
157static void setup(void)
158{
159	/* SIGFPE is expected signal, so avoid creating any corefile.
160	 * '1' is a special value, that will also avoid dumping via pipe. */
161	struct rlimit r;
162	r.rlim_cur = 1;
163	r.rlim_max = 1;
164	setrlimit(RLIMIT_CORE, &r);
165
166	TEST_PAUSE;
167}
168