blob: 425f2c4730298034cb540b1e9d1e8a0c7affed64 [file] [log] [blame]
/* IBM Corporation */
/* 01/02/2003 Port to LTP avenkat@us.ibm.com */
/* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
/*
*
* Copyright (c) International Business Machines Corp., 2002
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*kill1.c*/
/*======================================================================
>KEYS: < kill(), wait()
>WHAT: < Check that when a child is killed by its parent, it returns
< the correct values to the waiting parent--default behaviour
< assumed by child
>HOW: < For each signal: send that signal to a child, check that the
< child returns the correct value to the waiting parent.
>BUGS: <
>REQUIREMENT(S): Need to set ulimit to multiples of 1024.
======================================================================*/
#define _GNU_SOURCE 1
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
/***** LTP Port *****/
#include <errno.h>
#include "test.h"
#include "usctest.h"
#define ITER 3
#define FAILED 0
#define PASSED 1
char *TCID = "kill11";
int local_flag = PASSED;
int block_number;
FILE *temp;
int TST_TOTAL = 1;
extern int Tst_count;
static int sig;
int anyfail();
int blenter();
void setup();
void terror();
void fail_exit();
int forkfail();
void do_child();
/***** ** ** *****/
//char progname[] = "kill1()";
/*--------------------------------------------------------------------*/
int main(int argc, char **argv) /***** BEGINNING OF MAIN. *****/
{
int core;
int pid, npid;
int nsig, exno, nexno, status;
/*SIGIOT is 6, but since linux doesn't have SIGEMT, just using
SIGIOT for place filling */
int signum[14];
int j;
int ret_val = 0;
#ifdef UCLINUX
char *msg;
#endif
signum[1]=SIGHUP; signum[2]=SIGINT; signum[3]=SIGQUIT;
signum[4]=SIGILL; signum[5]=SIGTRAP; signum[6]=SIGABRT;
signum[7]=SIGIOT; signum[8]=SIGFPE; signum[9]=SIGKILL;
signum[10]=SIGBUS; signum[11]=SIGSEGV; signum[12]=SIGSYS;
signum[13]=SIGPIPE; signum[14]=SIGALRM;
#ifdef UCLINUX
/* parse standard options */
if ((msg = parse_opts(argc, argv, (option_t *)NULL, NULL)) != (char *)NULL){
tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
}
maybe_run_child(&do_child, "dd", &temp, &sig);
#endif
setup();
// tempdir(); /* move to new directory */
/*--------------------------------------------------------------------*/
blenter(); /*<<<<<ENTER DATA HERE<<<<<<<<*/
exno = 1;
unlink("core");
for(j = 1; j < 14; j++) {
sig=signum[j];
if (sig != SIGKILL )
#ifndef BCS
if( sig != SIGSTOP)
#endif
if (sigset(sig, SIG_DFL) == SIG_ERR) {
fprintf(temp, "\tsigset(%d,,) fails\n", sig);
local_flag = FAILED;
fail_exit();
}
fflush(temp);
pid = FORK_OR_VFORK();
if (pid < 0) {
forkfail();
}
/*
* Child process sleeps for up to 3 minutes giving the
* parent process a chance to kill it.
*/
if (pid == 0) {
#ifdef UCLINUX
if (self_exec(argv[0], "dd", temp, sig) < 0) {
tst_resm(TBROK, "self_exec FAILED - "
"terminating test.");
tst_exit();
return(0);
}
#else
do_child();
#endif
}
/*
* Parent process sends signal to child.
*/
//fprintf(temp, "Testing signal %d\n", sig); 12/12/02
kill (pid, sig);
npid = wait(&status);
if (npid != pid) {
fprintf(temp, "wait error: unexpected pid returned\n");
ret_val = 1;
}
/* 12/20/02.
nsig = status & 0177;
core = status & 0200;
nexno = (status & 0xff00) >> 8;
*/
/***** LTP Port *****/
nsig = WTERMSIG(status);
#ifdef WCOREDUMP
core = WCOREDUMP(status);
#endif
nexno = WIFEXITED(status);
/***** ** ** *****/
//printf("nsig=%x, core=%x, status=%x\n", nsig,core, status); 12/12/2002
/* to check if the core dump bit has been set, bit # 7 */
/***** LTP Port *****/
/* 12/12/02: avenkat@us.ibm.com
* SIGILL when is not caught or not ignored it causes
* a core dump and program termination. So moved the condition to
* else part of the program.
* SIGQUIT like SIGABRT normally causes a program to quit and
* and dumps core. So moved the condition to else part of the
* program.
*/
/***** ** ** *****/
if (core) {
if ((sig == 1) || (sig == 2) /*|| (sig == 3) ||*/
/*(sig == 4)*/ || (sig == 9) ||
(sig == 13) || (sig == 14) || (sig == 15)) {
fprintf(temp, "signal error: core dump bit set for exception number %d\n", sig);
ret_val = 1;
}
} else {
if((sig ==3) || (sig ==4) || (sig == 5) || (sig == 6) || (sig == 7) ||
(sig == 8) || (sig == 10) || (sig == 11) ||
(sig == 12)) {
fprintf(temp, "signal error: core dump bit not set for exception number %d\n", sig);
ret_val = 1;
}
}
/* nsig is the signal number returned by wait */
if (nsig != sig) {
fprintf(temp, "wait error: unexpected signal %d returned, expected %d\n", nsig, sig);
ret_val = 1;
}
/* nexno is the exit number returned by wait */
if (nexno != 0) {
fprintf(temp, "signal error: unexpected exit number %d returned, expected 0\n", nexno);
ret_val = 1;
}
}
unlink("core");
fflush(temp);
if(ret_val)
local_flag = FAILED;
unlink("core");
tst_rmdir();
/*--------------------------------------------------------------------*/
anyfail();
return(0);
}
/****** LTP Port *****/
int anyfail()
{
(local_flag == FAILED)? tst_resm(TFAIL, "Test failed\n"): tst_resm(TPASS, "Test passed\n");
tst_exit();
return(0);
}
void
do_child()
{
register int i;
int exno = 1;
for (i=0; i < 180; i++)
sleep(1);
fprintf(temp, "\tChild missed sig %d\n", sig);
fflush(temp);
_exit(exno);
}
void setup()
{
temp = stderr;
tst_tmpdir();
}
int blenter()
{
//tst_resm(TINFO, "Enter block %d\n", block_number);
local_flag = PASSED;
return(0);
}
void terror(char * message)
{
tst_resm(TBROK, "Reason: %s:%s\n", message, strerror(errno));
}
void fail_exit()
{
local_flag = FAILED;
anyfail();
}
int forkfail()
{
tst_resm(TBROK, "FORK FAILED - terminating test.");
tst_exit();
return(0);
}
/****** ** ** *******/