diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2024-10-17 09:11:36 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2024-10-17 09:11:36 +0000 |
commit | fafaaff49ea12a00d3072eb03fee68a49a892095 (patch) | |
tree | fd1ce3d4453b574447432b37966a2806290234db /sys/kern | |
parent | 8501f0c70effbf348c9dc1827581f418b7306ec6 (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.c | 21 | ||||
-rw-r--r-- | sys/kern/kern_synch.c | 4 |
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 |