From: claudio Date: Thu, 17 Oct 2024 09:11:35 +0000 (+0000) Subject: Shortcut cursig when called during sleep setup. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=3b30ff2ab7969af0fd9a5f043abb71c2592340bb;p=openbsd 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@ --- 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; @@ -1344,6 +1344,15 @@ cursig(struct proc *p, struct sigctx *sctx) if (sctx->sig_ignore && (pr->ps_flags & PS_TRACED) == 0) 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 @@ -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,