Add a test for r324671 along with some other masked tests.
MFC after: 1 week Sponsored by: Dell EMC Isilon
This commit is contained in:
parent
e69676a56d
commit
5e6f8d9e40
@ -2402,6 +2402,106 @@ ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_full_sigqueue, tc)
|
||||
ATF_REQUIRE(errno == ECHILD);
|
||||
}
|
||||
|
||||
static sem_t sigusr1_sem;
|
||||
static int got_usr1;
|
||||
|
||||
static void
|
||||
sigusr1_sempost_handler(int sig __unused)
|
||||
{
|
||||
|
||||
got_usr1++;
|
||||
CHILD_REQUIRE(sem_post(&sigusr1_sem) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that even if the signal queue is full for a child process,
|
||||
* and the signal is masked, a PT_CONTINUE with a signal will not
|
||||
* result in loss of that signal.
|
||||
*/
|
||||
ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
|
||||
ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue, tc)
|
||||
{
|
||||
struct ptrace_lwpinfo pl;
|
||||
pid_t fpid, wpid;
|
||||
int status, err;
|
||||
int max_pending_per_proc;
|
||||
size_t len;
|
||||
int i;
|
||||
sigset_t sigmask;
|
||||
|
||||
ATF_REQUIRE(signal(SIGUSR2, handler) != SIG_ERR);
|
||||
ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
|
||||
ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
|
||||
|
||||
got_usr1 = 0;
|
||||
ATF_REQUIRE((fpid = fork()) != -1);
|
||||
if (fpid == 0) {
|
||||
CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
|
||||
CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
|
||||
CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0);
|
||||
|
||||
trace_me();
|
||||
CHILD_REQUIRE(got_usr1 == 0);
|
||||
|
||||
/* Allow the pending SIGUSR1 in now. */
|
||||
CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
|
||||
/* Wait to receive the SIGUSR1. */
|
||||
do {
|
||||
err = sem_wait(&sigusr1_sem);
|
||||
CHILD_REQUIRE(err == 0 || errno == EINTR);
|
||||
} while (err != 0 && errno == EINTR);
|
||||
CHILD_REQUIRE(got_usr1 == 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The first wait() should report the stop from SIGSTOP. */
|
||||
wpid = waitpid(fpid, &status, 0);
|
||||
ATF_REQUIRE(wpid == fpid);
|
||||
ATF_REQUIRE(WIFSTOPPED(status));
|
||||
ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
|
||||
|
||||
len = sizeof(max_pending_per_proc);
|
||||
ATF_REQUIRE(sysctlbyname("kern.sigqueue.max_pending_per_proc",
|
||||
&max_pending_per_proc, &len, NULL, 0) == 0);
|
||||
|
||||
/* Fill the signal queue. */
|
||||
for (i = 0; i < max_pending_per_proc; ++i)
|
||||
ATF_REQUIRE(kill(fpid, SIGUSR2) == 0);
|
||||
|
||||
/* Continue with signal. */
|
||||
ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
|
||||
|
||||
/* Collect and ignore all of the SIGUSR2. */
|
||||
for (i = 0; i < max_pending_per_proc; ++i) {
|
||||
wpid = waitpid(fpid, &status, 0);
|
||||
ATF_REQUIRE(wpid == fpid);
|
||||
ATF_REQUIRE(WIFSTOPPED(status));
|
||||
ATF_REQUIRE(WSTOPSIG(status) == SIGUSR2);
|
||||
ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
|
||||
}
|
||||
|
||||
/* Now our PT_CONTINUE'd SIGUSR1 should cause a stop after unmask. */
|
||||
wpid = waitpid(fpid, &status, 0);
|
||||
ATF_REQUIRE(wpid == fpid);
|
||||
ATF_REQUIRE(WIFSTOPPED(status));
|
||||
ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1);
|
||||
ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
|
||||
ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1);
|
||||
|
||||
/* Continue the child, ignoring the SIGUSR1. */
|
||||
ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
|
||||
|
||||
/* The last wait() should report exit after receiving SIGUSR1. */
|
||||
wpid = waitpid(fpid, &status, 0);
|
||||
ATF_REQUIRE(wpid == fpid);
|
||||
ATF_REQUIRE(WIFEXITED(status));
|
||||
ATF_REQUIRE(WEXITSTATUS(status) == 1);
|
||||
|
||||
wpid = wait(&status);
|
||||
ATF_REQUIRE(wpid == -1);
|
||||
ATF_REQUIRE(errno == ECHILD);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that, after stopping due to a signal, that signal can be
|
||||
* replaced with another signal.
|
||||
@ -2674,15 +2774,6 @@ ATF_TC_BODY(ptrace__PT_CONTINUE_with_signal_kqueue, tc)
|
||||
ATF_REQUIRE(errno == ECHILD);
|
||||
}
|
||||
|
||||
static sem_t sigusr1_sem;
|
||||
|
||||
static void
|
||||
sigusr1_sempost_handler(int sig __unused)
|
||||
{
|
||||
|
||||
CHILD_REQUIRE(sem_post(&sigusr1_sem) == 0);
|
||||
}
|
||||
|
||||
static void *
|
||||
signal_thread(void *arg)
|
||||
{
|
||||
@ -2717,6 +2808,148 @@ signal_thread(void *arg)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that a traced process with blocked signal received the
|
||||
* signal from kill() once unmasked.
|
||||
*/
|
||||
ATF_TC_WITHOUT_HEAD(ptrace__killed_with_sigmask);
|
||||
ATF_TC_BODY(ptrace__killed_with_sigmask, tc)
|
||||
{
|
||||
struct ptrace_lwpinfo pl;
|
||||
pid_t fpid, wpid;
|
||||
int status, err;
|
||||
sigset_t sigmask;
|
||||
|
||||
ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
|
||||
ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
|
||||
got_usr1 = 0;
|
||||
|
||||
ATF_REQUIRE((fpid = fork()) != -1);
|
||||
if (fpid == 0) {
|
||||
CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
|
||||
CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
|
||||
CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0);
|
||||
|
||||
trace_me();
|
||||
CHILD_REQUIRE(got_usr1 == 0);
|
||||
|
||||
/* Allow the pending SIGUSR1 in now. */
|
||||
CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
|
||||
/* Wait to receive a SIGUSR1. */
|
||||
do {
|
||||
err = sem_wait(&sigusr1_sem);
|
||||
CHILD_REQUIRE(err == 0 || errno == EINTR);
|
||||
} while (err != 0 && errno == EINTR);
|
||||
CHILD_REQUIRE(got_usr1 == 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The first wait() should report the stop from SIGSTOP. */
|
||||
wpid = waitpid(fpid, &status, 0);
|
||||
ATF_REQUIRE(wpid == fpid);
|
||||
ATF_REQUIRE(WIFSTOPPED(status));
|
||||
ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
|
||||
ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
|
||||
ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGSTOP);
|
||||
|
||||
/* Send blocked SIGUSR1 which should cause a stop. */
|
||||
ATF_REQUIRE(kill(fpid, SIGUSR1) == 0);
|
||||
|
||||
/* Continue the child ignoring the SIGSTOP. */
|
||||
ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
|
||||
|
||||
/* The next wait() should report the kill(SIGUSR1) was received. */
|
||||
wpid = waitpid(fpid, &status, 0);
|
||||
ATF_REQUIRE(wpid == fpid);
|
||||
ATF_REQUIRE(WIFSTOPPED(status));
|
||||
ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1);
|
||||
ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
|
||||
ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1);
|
||||
|
||||
/* Continue the child, allowing in the SIGUSR1. */
|
||||
ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
|
||||
|
||||
/* The last wait() should report normal exit with code 1. */
|
||||
wpid = waitpid(fpid, &status, 0);
|
||||
ATF_REQUIRE(wpid == fpid);
|
||||
ATF_REQUIRE(WIFEXITED(status));
|
||||
ATF_REQUIRE(WEXITSTATUS(status) == 1);
|
||||
|
||||
wpid = wait(&status);
|
||||
ATF_REQUIRE(wpid == -1);
|
||||
ATF_REQUIRE(errno == ECHILD);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that a traced process with blocked signal received the
|
||||
* signal from PT_CONTINUE once unmasked.
|
||||
*/
|
||||
ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_with_sigmask);
|
||||
ATF_TC_BODY(ptrace__PT_CONTINUE_with_sigmask, tc)
|
||||
{
|
||||
struct ptrace_lwpinfo pl;
|
||||
pid_t fpid, wpid;
|
||||
int status, err;
|
||||
sigset_t sigmask;
|
||||
|
||||
ATF_REQUIRE(sem_init(&sigusr1_sem, 0, 0) == 0);
|
||||
ATF_REQUIRE(signal(SIGUSR1, sigusr1_sempost_handler) != SIG_ERR);
|
||||
got_usr1 = 0;
|
||||
|
||||
ATF_REQUIRE((fpid = fork()) != -1);
|
||||
if (fpid == 0) {
|
||||
CHILD_REQUIRE(sigemptyset(&sigmask) == 0);
|
||||
CHILD_REQUIRE(sigaddset(&sigmask, SIGUSR1) == 0);
|
||||
CHILD_REQUIRE(sigprocmask(SIG_BLOCK, &sigmask, NULL) == 0);
|
||||
|
||||
trace_me();
|
||||
CHILD_REQUIRE(got_usr1 == 0);
|
||||
|
||||
/* Allow the pending SIGUSR1 in now. */
|
||||
CHILD_REQUIRE(sigprocmask(SIG_UNBLOCK, &sigmask, NULL) == 0);
|
||||
/* Wait to receive a SIGUSR1. */
|
||||
do {
|
||||
err = sem_wait(&sigusr1_sem);
|
||||
CHILD_REQUIRE(err == 0 || errno == EINTR);
|
||||
} while (err != 0 && errno == EINTR);
|
||||
|
||||
CHILD_REQUIRE(got_usr1 == 1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* The first wait() should report the stop from SIGSTOP. */
|
||||
wpid = waitpid(fpid, &status, 0);
|
||||
ATF_REQUIRE(wpid == fpid);
|
||||
ATF_REQUIRE(WIFSTOPPED(status));
|
||||
ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
|
||||
ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
|
||||
ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGSTOP);
|
||||
|
||||
/* Continue the child replacing SIGSTOP with SIGUSR1. */
|
||||
ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, SIGUSR1) == 0);
|
||||
|
||||
/* The next wait() should report the SIGUSR1 was received. */
|
||||
wpid = waitpid(fpid, &status, 0);
|
||||
ATF_REQUIRE(wpid == fpid);
|
||||
ATF_REQUIRE(WIFSTOPPED(status));
|
||||
ATF_REQUIRE(WSTOPSIG(status) == SIGUSR1);
|
||||
ATF_REQUIRE(ptrace(PT_LWPINFO, fpid, (caddr_t)&pl, sizeof(pl)) != -1);
|
||||
ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGUSR1);
|
||||
|
||||
/* Continue the child, ignoring the SIGUSR1. */
|
||||
ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
|
||||
|
||||
/* The last wait() should report normal exit with code 1. */
|
||||
wpid = waitpid(fpid, &status, 0);
|
||||
ATF_REQUIRE(wpid == fpid);
|
||||
ATF_REQUIRE(WIFEXITED(status));
|
||||
ATF_REQUIRE(WEXITSTATUS(status) == 1);
|
||||
|
||||
wpid = wait(&status);
|
||||
ATF_REQUIRE(wpid == -1);
|
||||
ATF_REQUIRE(errno == ECHILD);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that if ptrace stops due to a signal but continues with
|
||||
* a different signal that the new signal is routed to a thread
|
||||
@ -3183,10 +3416,13 @@ ATF_TP_ADD_TCS(tp)
|
||||
ATF_TP_ADD_TC(tp,
|
||||
ptrace__PT_CONTINUE_with_signal_system_call_entry_and_exit);
|
||||
ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_full_sigqueue);
|
||||
ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_masked_full_sigqueue);
|
||||
ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_change_sig);
|
||||
ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigtrap_system_call_entry);
|
||||
ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_mix);
|
||||
ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_kqueue);
|
||||
ATF_TP_ADD_TC(tp, ptrace__killed_with_sigmask);
|
||||
ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigmask);
|
||||
ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_thread_sigmask);
|
||||
ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop1);
|
||||
ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop2);
|
||||
|
Loading…
x
Reference in New Issue
Block a user