-/* $OpenBSD: kern_sig.c,v 1.294 2022/02/14 11:26:05 claudio Exp $ */
+/* $OpenBSD: kern_sig.c,v 1.295 2022/03/11 10:05:38 claudio Exp $ */
/* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */
/*
p->p_sicode = code;
p->p_sigval = sigval;
+ /*
+ * If traced, stop if signal is masked, and stay stopped
+ * until released by the debugger. If our parent process
+ * is waiting for us, don't hang as we could deadlock.
+ */
+ if (((pr->ps_flags & (PS_TRACED | PS_PPWAIT)) == PS_TRACED) &&
+ signum != SIGKILL && (p->p_sigmask & mask) != 0) {
+ int s;
+
+ pr->ps_xsig = signum;
+
+ single_thread_set(p, SINGLE_SUSPEND, 0);
+
+ SCHED_LOCK(s);
+ proc_stop(p, 1);
+ SCHED_UNLOCK(s);
+
+ single_thread_clear(p, 0);
+
+ /*
+ * If we are no longer being traced, or the parent
+ * didn't give us a signal, skip sending the signal.
+ */
+ if ((pr->ps_flags & PS_TRACED) == 0 ||
+ pr->ps_xsig == 0) {
+ KERNEL_UNLOCK();
+ return;
+ }
+
+ /* update signal info */
+ signum = pr->ps_xsig;
+ p->p_sisig = signum;
+ mask = sigmask(signum);
+ }
+
/*
* Signals like SIGBUS and SIGSEGV should not, when
* generated by the kernel, be ignorable or blockable.
KASSERT(p == curproc);
for (;;) {
- mask = (p->p_siglist | pr->ps_siglist);
- if (!ISSET(pr->ps_flags, PS_TRACED))
- mask &= ~p->p_sigmask;
+ mask = SIGPENDING(p);
if (pr->ps_flags & PS_PPWAIT)
mask &= ~STOPSIGMASK;
if (mask == 0) /* no signal to send */
KERNEL_UNLOCK();
}
- if (SIGPENDING(p) != 0 || ISSET(p->p_p->ps_flags, PS_TRACED)) {
+ if (SIGPENDING(p) != 0) {
KERNEL_LOCK();
while ((signum = cursig(p, &ctx)) != 0)
postsig(p, signum, &ctx);