From fafaaff49ea12a00d3072eb03fee68a49a892095 Mon Sep 17 00:00:00 2001 From: Claudio Jeker Date: Thu, 17 Oct 2024 09:11:36 +0000 Subject: 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@ --- sys/kern/kern_sig.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'sys/kern/kern_sig.c') 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); } -- cgit v1.2.3