summaryrefslogtreecommitdiff
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
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@
-rw-r--r--sys/kern/kern_sig.c21
-rw-r--r--sys/kern/kern_synch.c4
-rw-r--r--sys/sys/signalvar.h4
-rw-r--r--sys/ufs/mfs/mfs_vfsops.c4
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,