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 
60 static void do_child(void);
61 static void setup(void);
62 
63 char *TCID = "waitpid02";
64 int TST_TOTAL = 1;
65 
main(int argc,char ** argv)66 int 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 
do_child(void)147 static void do_child(void)
148 {
149 	int exno = 1;
150 
151 	while (1)
152 		usleep(10);
153 
154 	exit(exno);
155 }
156 
setup(void)157 static 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