Home | History | Annotate | Download | only in waitpid
      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 
     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 
    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  */
    224 static void do_child_uclinux(void)
    225 {
    226 	do_child(sig_uclinux);
    227 }
    228 #endif
    229 
    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 
    244 static void cleanup(void)
    245 {
    246 	tst_rmdir();
    247 }
    248