Ignore interception of SIGCHLD signals in the debugger

Set SIGPASS for SIGCHLD for the traced child in the following tests:

 - posix_spawn_singalmasked
 - posix_spawn_singalignored
 - fork_singalmasked
 - fork_singalignored
 - vfork_singalmasked
 - vfork_singalignored
 - vforkdone_singalmasked
 - vforkdone_singalignored

There is a race that SIGCHLD might be blocked during forking and dropped.

PR/55241 by Andreas Gustafsson
This commit is contained in:
kamil 2020-05-16 19:08:20 +00:00
parent c00e7542d4
commit 985ba7a358
1 changed files with 15 additions and 11 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: t_ptrace_fork_wait.h,v 1.3 2020/05/14 19:21:35 kamil Exp $ */
/* $NetBSD: t_ptrace_fork_wait.h,v 1.4 2020/05/16 19:08:20 kamil Exp $ */
/*-
* Copyright (c) 2016, 2017, 2018, 2020 The NetBSD Foundation, Inc.
@ -1250,6 +1250,7 @@ fork2_body(const char *fn, bool masked, bool ignored)
int name[6];
const size_t namelen = __arraycount(name);
sigset_t set;
ki_sigset_t kp_sigmask;
ki_sigset_t kp_sigignore;
@ -1341,6 +1342,19 @@ fork2_body(const char *fn, bool masked, bool ignored)
event.pe_set_event |= PTRACE_VFORK_DONE;
SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
/*
* Ignore interception of the SIGCHLD signals.
*
* SIGCHLD once blocked is discarded by the kernel as it has the
* SA_IGNORE property. During the fork(2) operation all signals can be
* shortly blocked and missed (unless there is a registered signal
* handler in the traced child). This leads to a race in this test if
* there would be an intention to catch SIGCHLD.
*/
sigemptyset(&set);
sigaddset(&set, SIGCHLD);
SYSCALL_REQUIRE(ptrace(PT_SET_SIGPASS, child, &set, sizeof(set)) != -1);
DPRINTF("Before resuming the child process where it left off and "
"without signal to be sent\n");
SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
@ -1560,16 +1574,6 @@ fork2_body(const char *fn, bool masked, bool ignored)
wpid = TWAIT_GENERIC(child2, &status, 0));
}
DPRINTF("Before calling %s() for the child - expected stopped "
"SIGCHLD\n", TWAIT_FNAME);
TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
validate_status_stopped(status, SIGCHLD);
DPRINTF("Before resuming the child process where it left off and "
"without signal to be sent\n");
SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
DPRINTF("Before calling %s() for the child - expected exited\n",
TWAIT_FNAME);
TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);