summaryrefslogtreecommitdiff
path: root/sys/kern/kern_sig.c
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2024-11-06 17:14:02 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2024-11-06 17:14:02 +0000
commit01329a5aeec53e7f3a4179e30bf02b4a236ce365 (patch)
tree8d8c1fa893ae82a2930f86dd2eef7a0a047585d6 /sys/kern/kern_sig.c
parentbe67c1623e5cff64b38112356f5fa4175040881d (diff)
Factor out the ptrace trap into proc_trap() and simplify the signal
delivery in cursig() a lot since most of that is no longer needed. On top of this properly handle sending a blocked signal from gdb to the debugged process by putting the signal into to proc p_siglist. OK kettenis@
Diffstat (limited to 'sys/kern/kern_sig.c')
-rw-r--r--sys/kern/kern_sig.c80
1 files changed, 36 insertions, 44 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index e8e45c9517b..f3dd6f79b45 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sig.c,v 1.347 2024/11/05 09:14:19 claudio Exp $ */
+/* $OpenBSD: kern_sig.c,v 1.348 2024/11/06 17:14:01 claudio Exp $ */
/* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */
/*
@@ -115,6 +115,7 @@ const int sigprop[NSIG] = {
void setsigvec(struct proc *, int, struct sigaction *);
+int proc_trap(struct proc *, int);
void proc_stop(struct proc *p, int);
void proc_stop_sweep(void *);
void *proc_stop_si;
@@ -834,30 +835,20 @@ trapsignal(struct proc *p, int signum, u_long trapno, int code,
*/
if (((pr->ps_flags & (PS_TRACED | PS_PPWAIT)) == PS_TRACED) &&
signum != SIGKILL && (p->p_sigmask & mask) != 0) {
- single_thread_set(p, SINGLE_SUSPEND | SINGLE_NOWAIT);
- pr->ps_xsig = signum;
-
- SCHED_LOCK();
- proc_stop(p, 1);
- SCHED_UNLOCK();
+ signum = proc_trap(p, signum);
- signum = pr->ps_xsig;
- pr->ps_xsig = 0;
- if ((p->p_flag & P_TRACESINGLE) == 0)
- single_thread_clear(p, 0);
- atomic_clearbits_int(&p->p_flag, P_TRACESINGLE);
+ mask = sigmask(signum);
+ setsigctx(p, signum, &ctx);
/*
* 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 ||
- signum == 0)
+ if ((pr->ps_flags & PS_TRACED) == 0 || signum == 0)
return;
/* update signal info */
p->p_sisig = signum;
- mask = sigmask(signum);
}
/*
@@ -1386,48 +1377,28 @@ cursig(struct proc *p, struct sigctx *sctx, int deep)
*/
if (((pr->ps_flags & (PS_TRACED | PS_PPWAIT)) == PS_TRACED) &&
signum != SIGKILL) {
- single_thread_set(p, SINGLE_SUSPEND | SINGLE_NOWAIT);
- pr->ps_xsig = signum;
-
- SCHED_LOCK();
- proc_stop(p, 1);
- SCHED_UNLOCK();
+ signum = proc_trap(p, signum);
- /*
- * re-take the signal before releasing
- * the other threads. Must check the continue
- * conditions below and only take the signal if
- * those are not true.
- */
- signum = pr->ps_xsig;
- pr->ps_xsig = 0;
mask = sigmask(signum);
setsigctx(p, signum, sctx);
- if (!((pr->ps_flags & PS_TRACED) == 0 ||
- signum == 0 ||
- (p->p_sigmask & mask) != 0)) {
- atomic_clearbits_int(&p->p_siglist, mask);
- atomic_clearbits_int(&pr->ps_siglist, mask);
- }
-
- if ((p->p_flag & P_TRACESINGLE) == 0)
- single_thread_clear(p, 0);
- atomic_clearbits_int(&p->p_flag, P_TRACESINGLE);
/*
* If we are no longer being traced, or the parent
- * didn't give us a signal, look for more signals.
+ * didn't give us a signal, or the signal is ignored,
+ * look for more signals.
*/
- if ((pr->ps_flags & PS_TRACED) == 0 ||
- signum == 0)
+ if ((pr->ps_flags & PS_TRACED) == 0 || signum == 0 ||
+ sctx->sig_ignore)
continue;
/*
* If the new signal is being masked, look for other
- * signals.
+ * signals but leave it for later.
*/
- if ((p->p_sigmask & mask) != 0)
+ if ((p->p_sigmask & mask) != 0) {
+ atomic_setbits_int(&p->p_siglist, mask);
continue;
+ }
}
@@ -1507,6 +1478,27 @@ keep:
return (signum);
}
+int
+proc_trap(struct proc *p, int signum)
+{
+ struct process *pr = p->p_p;
+
+ single_thread_set(p, SINGLE_SUSPEND | SINGLE_NOWAIT);
+ pr->ps_xsig = signum;
+
+ SCHED_LOCK();
+ proc_stop(p, 1);
+ SCHED_UNLOCK();
+
+ signum = pr->ps_xsig;
+ pr->ps_xsig = 0;
+ if ((p->p_flag & P_TRACESINGLE) == 0)
+ single_thread_clear(p, 0);
+ atomic_clearbits_int(&p->p_flag, P_TRACESINGLE);
+
+ return signum;
+}
+
/*
* Put the argument process into the stopped state and notify the parent
* via wakeup. Signals are handled elsewhere. The process must not be