You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
213 lines
4.1 KiB
213 lines
4.1 KiB
/* 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
|
|
* Copyright (c) Cyril Hrubis <chrubis@suse.cz> 2014
|
|
*
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/*
|
|
|
|
Test check that when a child is killed by its parent, it returns the correct
|
|
values to the waiting parent--default behaviour assumed by child.
|
|
|
|
*/
|
|
|
|
#define _GNU_SOURCE 1
|
|
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <sys/types.h>
|
|
#include <signal.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/resource.h>
|
|
|
|
#include "test.h"
|
|
#include "safe_macros.h"
|
|
|
|
#define FAILED 0
|
|
#define PASSED 1
|
|
|
|
char *TCID = "kill11";
|
|
|
|
int local_flag = PASSED;
|
|
int block_number;
|
|
FILE *temp;
|
|
int TST_TOTAL = 1;
|
|
static int sig;
|
|
|
|
void setup(void);
|
|
void do_child(void);
|
|
|
|
/*
|
|
* These signals terminate process by default, some create core file.
|
|
*/
|
|
struct tcase {
|
|
int sig;
|
|
int dumps_core;
|
|
} tcases[] = {
|
|
{SIGHUP, 0},
|
|
{SIGINT, 0},
|
|
{SIGQUIT, 1},
|
|
{SIGILL, 1},
|
|
{SIGTRAP, 1},
|
|
{SIGABRT, 1},
|
|
{SIGIOT, 1},
|
|
{SIGBUS, 1},
|
|
{SIGFPE, 1},
|
|
{SIGKILL, 0},
|
|
{SIGUSR1, 0},
|
|
{SIGSEGV, 1},
|
|
{SIGUSR2, 0},
|
|
{SIGPIPE, 0},
|
|
{SIGALRM, 0},
|
|
{SIGTERM, 0},
|
|
{SIGXCPU, 1},
|
|
{SIGXFSZ, 1},
|
|
{SIGVTALRM, 0},
|
|
{SIGPROF, 0},
|
|
{SIGIO, 0},
|
|
{SIGPWR, 0},
|
|
{SIGSYS, 1},
|
|
};
|
|
|
|
static void verify_kill(struct tcase *t)
|
|
{
|
|
int core;
|
|
int pid, npid;
|
|
int nsig, nexno, status;
|
|
|
|
if (t->sig != SIGKILL) {
|
|
#ifndef BCS
|
|
if (t->sig != SIGSTOP)
|
|
#endif
|
|
if (sigset(t->sig, SIG_DFL) == SIG_ERR) {
|
|
tst_brkm(TBROK | TERRNO, tst_rmdir,
|
|
"sigset(%d) failed", sig);
|
|
}
|
|
}
|
|
|
|
pid = FORK_OR_VFORK();
|
|
if (pid < 0)
|
|
tst_brkm(TBROK | TERRNO, tst_rmdir, "fork() failed");
|
|
|
|
if (pid == 0) {
|
|
#ifdef UCLINUX
|
|
if (self_exec(argv[0], "dd", t->sig) < 0)
|
|
exit(1);
|
|
#else
|
|
do_child();
|
|
#endif
|
|
}
|
|
|
|
kill(pid, t->sig);
|
|
npid = wait(&status);
|
|
|
|
if (npid != pid) {
|
|
tst_resm(TFAIL, "wait() returned %d, expected %d", npid, pid);
|
|
return;
|
|
}
|
|
|
|
nsig = WTERMSIG(status);
|
|
#ifdef WCOREDUMP
|
|
core = WCOREDUMP(status);
|
|
#endif
|
|
nexno = WIFEXITED(status);
|
|
|
|
if (t->dumps_core) {
|
|
if (!core) {
|
|
tst_resm(TFAIL, "core dump bit not set for %s", tst_strsig(t->sig));
|
|
return;
|
|
}
|
|
} else {
|
|
if (core) {
|
|
tst_resm(TFAIL, "core dump bit set for %s", tst_strsig(t->sig));
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (nsig != t->sig) {
|
|
tst_resm(TFAIL, "wait: unexpected signal %d returned, expected %d", nsig, t->sig);
|
|
return;
|
|
}
|
|
|
|
if (nexno != 0) {
|
|
tst_resm(TFAIL,
|
|
"signal: unexpected exit number %d returned, expected 0\n",
|
|
nexno);
|
|
return;
|
|
}
|
|
|
|
tst_resm(TPASS, "signal %-16s%s", tst_strsig(t->sig),
|
|
t->dumps_core ? " dumped core" : "");
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
int lc;
|
|
unsigned int i;
|
|
|
|
tst_parse_opts(argc, argv, NULL, NULL);
|
|
|
|
#ifdef UCLINUX
|
|
maybe_run_child(&do_child, "dd", &sig);
|
|
#endif
|
|
|
|
setup();
|
|
|
|
for (lc = 0; TEST_LOOPING(lc); lc++) {
|
|
for (i = 0; i < ARRAY_SIZE(tcases); i++)
|
|
verify_kill(tcases + i);
|
|
}
|
|
|
|
tst_rmdir();
|
|
tst_exit();
|
|
}
|
|
|
|
void do_child(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 180; i++)
|
|
sleep(1);
|
|
|
|
fprintf(stderr, "Child missed siggnal");
|
|
fflush(stderr);
|
|
exit(1);
|
|
}
|
|
|
|
/* 1024 GNU blocks */
|
|
#define MIN_RLIMIT_CORE (1024 * 1024)
|
|
|
|
void setup(void)
|
|
{
|
|
struct rlimit rlim;
|
|
|
|
SAFE_GETRLIMIT(NULL, RLIMIT_CORE, &rlim);
|
|
|
|
if (rlim.rlim_cur < MIN_RLIMIT_CORE) {
|
|
tst_resm(TINFO, "Adjusting RLIMIT_CORE to %i", MIN_RLIMIT_CORE);
|
|
rlim.rlim_cur = MIN_RLIMIT_CORE;
|
|
SAFE_SETRLIMIT(NULL, RLIMIT_CORE, &rlim);
|
|
}
|
|
|
|
temp = stderr;
|
|
tst_tmpdir();
|
|
}
|