summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2024-10-17 09:11:36 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2024-10-17 09:11:36 +0000
commitfafaaff49ea12a00d3072eb03fee68a49a892095 (patch)
treefd1ce3d4453b574447432b37966a2806290234db /sys/kern
parent8501f0c70effbf348c9dc1827581f418b7306ec6 (diff)
Shortcut cursig when called during sleep setup.
Add deep flag as function argument which is used by the sleep API but nowhere else. Both calls to sleep_signal_check() should skip the ugly bits of cursig(). In cursig() if deep once it is clear a signal will be taken keep the signal on the thread siglist and return. sleep_signal_check() will then return EINTR or ERESTART based on the signal context. There is no reason to do more in this special case. Especially stop/cont and the ptrace trap must be skipped here. Once the call makes it to userret the signal will be picked up again and handled in a safe location. Stopping singals need some additional logic since we don't want to abort the sleep just to stop a process. Since our SIGSTOP handling requires a major rewrite this will be posponed until then. OK mpi@
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_sig.c21
-rw-r--r--sys/kern/kern_synch.c4
2 files changed, 17 insertions, 8 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index c0576093843..98edd7378d5 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sig.c,v 1.342 2024/10/15 13:49:26 claudio Exp $ */
+/* $OpenBSD: kern_sig.c,v 1.343 2024/10/17 09:11:35 claudio Exp $ */
/* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */
/*
@@ -1302,14 +1302,14 @@ setsigctx(struct proc *p, int signum, struct sigctx *sctx)
* they aren't returned. This is checked after each entry to the system for
* a syscall or trap. The normal call sequence is
*
- * while (signum = cursig(curproc, &ctx))
+ * while (signum = cursig(curproc, &ctx, 0))
* postsig(signum, &ctx);
*
* Assumes that if the P_SINTR flag is set, we're holding both the
* kernel and scheduler locks.
*/
int
-cursig(struct proc *p, struct sigctx *sctx)
+cursig(struct proc *p, struct sigctx *sctx, int deep)
{
struct process *pr = p->p_p;
int signum, mask, prop;
@@ -1345,6 +1345,15 @@ cursig(struct proc *p, struct sigctx *sctx)
continue;
/*
+ * If cursig is called while going to sleep, abort now
+ * and stop the sleep. When the call unwinded to userret
+ * cursig is called again and there the signal can be
+ * handled cleanly.
+ */
+ if (deep)
+ goto keep;
+
+ /*
* If traced, always stop, and stay stopped until released
* by the debugger. If our parent process is waiting for
* us, don't hang as we could deadlock.
@@ -1915,7 +1924,7 @@ sys___thrsigdivert(struct proc *p, void *v, register_t *retval)
dosigsuspend(p, p->p_sigmask &~ mask);
for (;;) {
- si.si_signo = cursig(p, &ctx);
+ si.si_signo = cursig(p, &ctx, 0);
if (si.si_signo != 0) {
sigset_t smask = sigmask(si.si_signo);
if (smask & mask) {
@@ -2006,7 +2015,7 @@ userret(struct proc *p)
}
if (SIGPENDING(p) != 0) {
- while ((signum = cursig(p, &ctx)) != 0)
+ while ((signum = cursig(p, &ctx, 0)) != 0)
postsig(p, signum, &ctx);
}
@@ -2020,7 +2029,7 @@ userret(struct proc *p)
p->p_sigmask = p->p_oldmask;
atomic_clearbits_int(&p->p_flag, P_SIGSUSPEND);
- while ((signum = cursig(p, &ctx)) != 0)
+ while ((signum = cursig(p, &ctx, 0)) != 0)
postsig(p, signum, &ctx);
}
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
index cbbb473dfc0..dda123c1d9b 100644
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_synch.c,v 1.206 2024/07/23 08:38:02 claudio Exp $ */
+/* $OpenBSD: kern_synch.c,v 1.207 2024/10/17 09:11:35 claudio Exp $ */
/* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */
/*
@@ -458,7 +458,7 @@ sleep_signal_check(struct proc *p)
if ((err = single_thread_check(p, 1)) != 0)
return err;
- if ((sig = cursig(p, &ctx)) != 0) {
+ if ((sig = cursig(p, &ctx, 1)) != 0) {
if (ctx.sig_intr)
return EINTR;
else