132 lines
2.6 KiB
C
132 lines
2.6 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/* 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
|
|
*
|
|
* Test checks that when a child is killed by its parent with sig, it
|
|
* returns the correct values(sig and core dump bit) to the waiting parent.
|
|
*
|
|
* RESTRICTIONS
|
|
* The ulimit for core file size must be greater than 0.
|
|
*/
|
|
|
|
#define _GNU_SOURCE
|
|
#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 "tst_test.h"
|
|
|
|
static 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},
|
|
#ifdef SIGSTKFLT
|
|
{SIGSTKFLT, 0},
|
|
#endif
|
|
{SIGXCPU, 1},
|
|
{SIGXFSZ, 1},
|
|
{SIGVTALRM, 0},
|
|
{SIGPROF, 0},
|
|
{SIGIO, 0},
|
|
{SIGPWR, 0},
|
|
{SIGSYS, 1},
|
|
};
|
|
|
|
static void verify_kill(unsigned int n)
|
|
{
|
|
int core;
|
|
pid_t pid, npid;
|
|
int nsig, status;
|
|
struct tcase *tc = &tcases[n];
|
|
|
|
pid = SAFE_FORK();
|
|
if (!pid)
|
|
pause();
|
|
|
|
SAFE_KILL(pid, tc->sig);
|
|
npid = SAFE_WAIT(&status);
|
|
|
|
if (npid != pid) {
|
|
tst_res(TFAIL, "wait() returned %d, expected %d", npid, pid);
|
|
return;
|
|
}
|
|
|
|
nsig = WTERMSIG(status);
|
|
core = WCOREDUMP(status);
|
|
|
|
if (tc->dumps_core) {
|
|
if (!core) {
|
|
tst_res(TFAIL, "core dump bit not set for %s", tst_strsig(tc->sig));
|
|
return;
|
|
}
|
|
} else {
|
|
if (core) {
|
|
tst_res(TFAIL, "core dump bit set for %s", tst_strsig(tc->sig));
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (nsig != tc->sig) {
|
|
tst_res(TFAIL, "wait: unexpected signal %d returned, expected %d", nsig, tc->sig);
|
|
return;
|
|
}
|
|
|
|
tst_res(TPASS, "signal %-16s%s", tst_strsig(tc->sig),
|
|
tc->dumps_core ? " dumped core" : "");
|
|
}
|
|
|
|
#define MIN_RLIMIT_CORE (512 * 1024)
|
|
|
|
static void setup(void)
|
|
{
|
|
struct rlimit rlim;
|
|
|
|
SAFE_GETRLIMIT(RLIMIT_CORE, &rlim);
|
|
|
|
if (rlim.rlim_max < MIN_RLIMIT_CORE) {
|
|
if (geteuid() != 0) {
|
|
tst_brk(TCONF, "hard limit(%lu)less than MIN_RLIMT_CORE(%i)",
|
|
rlim.rlim_max, MIN_RLIMIT_CORE);
|
|
}
|
|
tst_res(TINFO, "Raising rlim_max to %i", MIN_RLIMIT_CORE);
|
|
rlim.rlim_max = MIN_RLIMIT_CORE;
|
|
}
|
|
if (rlim.rlim_cur < MIN_RLIMIT_CORE) {
|
|
tst_res(TINFO, "Adjusting RLIMIT_CORE to %i", MIN_RLIMIT_CORE);
|
|
rlim.rlim_cur = MIN_RLIMIT_CORE;
|
|
SAFE_SETRLIMIT(RLIMIT_CORE, &rlim);
|
|
}
|
|
}
|
|
|
|
static struct tst_test test = {
|
|
.needs_tmpdir = 1,
|
|
.forks_child = 1,
|
|
.setup = setup,
|
|
.tcnt = ARRAY_SIZE(tcases),
|
|
.test = verify_kill,
|
|
};
|