Home | History | Annotate | Download | only in kill
      1 /* IBM Corporation
      2  * 01/02/2003	Port to LTP	avenkat (at) us.ibm.com
      3  * 06/30/2001	Port to Linux	nsharoff (at) us.ibm.com
      4  *
      5  *   Copyright (c) International Business Machines  Corp., 2002
      6  *   Copyright (c) Cyril Hrubis <chrubis (at) suse.cz> 2014
      7  *
      8  *   This program is free software;  you can redistribute it and/or modify
      9  *   it under the terms of the GNU General Public License as published by
     10  *   the Free Software Foundation; either version 2 of the License, or
     11  *   (at your option) any later version.
     12  *
     13  *   This program is distributed in the hope that it will be useful,
     14  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
     15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
     16  *   the GNU General Public License for more details.
     17  *
     18  *   You should have received a copy of the GNU General Public License
     19  *   along with this program;  if not, write to the Free Software
     20  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     21  */
     22 
     23 /*
     24 
     25   Test check that when a child is killed by its parent, it returns the correct
     26   values to the waiting parent--default behaviour assumed by child.
     27 
     28  */
     29 
     30 #define _GNU_SOURCE 1
     31 
     32 #include <stdio.h>
     33 #include <errno.h>
     34 #include <sys/types.h>
     35 #include <signal.h>
     36 #include <stdlib.h>
     37 #include <unistd.h>
     38 #include <sys/wait.h>
     39 #include <sys/resource.h>
     40 
     41 #include "test.h"
     42 #include "safe_macros.h"
     43 
     44 #define FAILED 0
     45 #define PASSED 1
     46 
     47 char *TCID = "kill11";
     48 
     49 int local_flag = PASSED;
     50 int block_number;
     51 FILE *temp;
     52 int TST_TOTAL = 1;
     53 static int sig;
     54 
     55 void setup(void);
     56 void do_child(void);
     57 
     58 /*
     59  * These signals terminate process by default, some create core file.
     60  */
     61 struct tcase {
     62 	int sig;
     63 	int dumps_core;
     64 } tcases[] = {
     65 	{SIGHUP, 0},
     66 	{SIGINT, 0},
     67 	{SIGQUIT, 1},
     68 	{SIGILL, 1},
     69 	{SIGTRAP, 1},
     70 	{SIGABRT, 1},
     71 	{SIGIOT, 1},
     72 	{SIGBUS, 1},
     73 	{SIGFPE, 1},
     74 	{SIGKILL, 0},
     75 	{SIGUSR1, 0},
     76 	{SIGSEGV, 1},
     77 	{SIGUSR2, 0},
     78 	{SIGPIPE, 0},
     79 	{SIGALRM, 0},
     80 	{SIGTERM, 0},
     81 	{SIGXCPU, 1},
     82 	{SIGXFSZ, 1},
     83 	{SIGVTALRM, 0},
     84 	{SIGPROF, 0},
     85 	{SIGIO, 0},
     86 	{SIGPWR, 0},
     87 	{SIGSYS, 1},
     88 };
     89 
     90 static void verify_kill(struct tcase *t)
     91 {
     92 	int core;
     93 	int pid, npid;
     94 	int nsig, nexno, status;
     95 
     96 	if (t->sig != SIGKILL) {
     97 #ifndef BCS
     98 		if (t->sig != SIGSTOP)
     99 #endif
    100 			if (sigset(t->sig, SIG_DFL) == SIG_ERR) {
    101 				tst_brkm(TBROK | TERRNO, tst_rmdir,
    102 				         "sigset(%d) failed", sig);
    103 			}
    104 	}
    105 
    106 	pid = FORK_OR_VFORK();
    107 	if (pid < 0)
    108 		tst_brkm(TBROK | TERRNO, tst_rmdir, "fork() failed");
    109 
    110 	if (pid == 0) {
    111 #ifdef UCLINUX
    112 		if (self_exec(argv[0], "dd", t->sig) < 0)
    113 			exit(1);
    114 #else
    115 		do_child();
    116 #endif
    117 	}
    118 
    119 	kill(pid, t->sig);
    120 	npid = wait(&status);
    121 
    122 	if (npid != pid) {
    123 		tst_resm(TFAIL, "wait() returned %d, expected %d", npid, pid);
    124 		return;
    125 	}
    126 
    127 	nsig = WTERMSIG(status);
    128 #ifdef WCOREDUMP
    129 	core = WCOREDUMP(status);
    130 #endif
    131 	nexno = WIFEXITED(status);
    132 
    133 	if (t->dumps_core) {
    134 		if (!core) {
    135 			tst_resm(TFAIL, "core dump bit not set for %s", tst_strsig(t->sig));
    136 			return;
    137 		}
    138 	} else {
    139 		if (core) {
    140 			tst_resm(TFAIL, "core dump bit set for %s", tst_strsig(t->sig));
    141 			return;
    142 		}
    143 	}
    144 
    145 	if (nsig != t->sig) {
    146 		tst_resm(TFAIL, "wait: unexpected signal %d returned, expected %d", nsig, t->sig);
    147 		return;
    148 	}
    149 
    150 	if (nexno != 0) {
    151 		tst_resm(TFAIL,
    152 			"signal: unexpected exit number %d returned, expected 0\n",
    153 			nexno);
    154 		return;
    155 	}
    156 
    157 	tst_resm(TPASS, "signal %-16s%s", tst_strsig(t->sig),
    158 	         t->dumps_core ? " dumped core" : "");
    159 }
    160 
    161 int main(int argc, char **argv)
    162 {
    163 	int lc;
    164 	unsigned int i;
    165 
    166 	tst_parse_opts(argc, argv, NULL, NULL);
    167 
    168 #ifdef UCLINUX
    169 	maybe_run_child(&do_child, "dd", &sig);
    170 #endif
    171 
    172 	setup();
    173 
    174 	for (lc = 0; TEST_LOOPING(lc); lc++) {
    175 		for (i = 0; i < ARRAY_SIZE(tcases); i++)
    176 			verify_kill(tcases + i);
    177 	}
    178 
    179 	tst_rmdir();
    180 	tst_exit();
    181 }
    182 
    183 void do_child(void)
    184 {
    185 	int i;
    186 
    187 	for (i = 0; i < 180; i++)
    188 		sleep(1);
    189 
    190 	fprintf(stderr, "Child missed siggnal");
    191 	fflush(stderr);
    192 	exit(1);
    193 }
    194 
    195 /* 1024 GNU blocks */
    196 #define MIN_RLIMIT_CORE (1024 * 1024)
    197 
    198 void setup(void)
    199 {
    200 	struct rlimit rlim;
    201 
    202 	SAFE_GETRLIMIT(NULL, RLIMIT_CORE, &rlim);
    203 
    204 	if (rlim.rlim_cur < MIN_RLIMIT_CORE) {
    205 		tst_resm(TINFO, "Adjusting RLIMIT_CORE to %i", MIN_RLIMIT_CORE);
    206 		rlim.rlim_cur = MIN_RLIMIT_CORE;
    207 		SAFE_SETRLIMIT(NULL, RLIMIT_CORE, &rlim);
    208 	}
    209 
    210 	temp = stderr;
    211 	tst_tmpdir();
    212 }
    213