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 | |
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@
-rw-r--r-- | sys/kern/kern_sig.c | 21 | ||||
-rw-r--r-- | sys/kern/kern_synch.c | 4 | ||||
-rw-r--r-- | sys/sys/signalvar.h | 4 | ||||
-rw-r--r-- | sys/ufs/mfs/mfs_vfsops.c | 4 |
4 files changed, 21 insertions, 12 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 diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h index a8c6168f7ef..c207cff214a 100644 --- a/sys/sys/signalvar.h +++ b/sys/sys/signalvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: signalvar.h,v 1.55 2024/10/09 08:39:49 claudio Exp $ */ +/* $OpenBSD: signalvar.h,v 1.56 2024/10/17 09:11:35 claudio Exp $ */ /* $NetBSD: signalvar.h,v 1.17 1996/04/22 01:23:31 christos Exp $ */ /* @@ -109,7 +109,7 @@ struct sigctx { */ int coredump(struct proc *p); void execsigs(struct proc *p); -int cursig(struct proc *p, struct sigctx *); +int cursig(struct proc *p, struct sigctx *, int); void pgsigio(struct sigio_ref *sir, int sig, int checkctty); void pgsignal(struct pgrp *pgrp, int sig, int checkctty); void psignal(struct proc *p, int sig); diff --git a/sys/ufs/mfs/mfs_vfsops.c b/sys/ufs/mfs/mfs_vfsops.c index ff6d46997f6..4ce1859b773 100644 --- a/sys/ufs/mfs/mfs_vfsops.c +++ b/sys/ufs/mfs/mfs_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mfs_vfsops.c,v 1.62 2022/02/14 11:26:05 claudio Exp $ */ +/* $OpenBSD: mfs_vfsops.c,v 1.63 2024/10/17 09:11:35 claudio Exp $ */ /* $NetBSD: mfs_vfsops.c,v 1.10 1996/02/09 22:31:28 christos Exp $ */ /* @@ -189,7 +189,7 @@ mfs_start(struct mount *mp, int flags, struct proc *p) * EINTR/ERESTART. */ if (sleepreturn != 0) { - sig = cursig(p, &ctx); + sig = cursig(p, &ctx, 0); if (vfs_busy(mp, VB_WRITE|VB_NOWAIT) || dounmount(mp, (sig == SIGKILL) ? MNT_FORCE : 0, p)) atomic_clearbits_int(&p->p_siglist, |