Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 9 Apr 2021 20:44:32 GMT
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: dc47fdf1319f - main - Stop arming periodic process timers on suspend or terminate
Message-ID:  <202104092044.139KiWv5070966@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=dc47fdf1319f18be1aadbcdef17c721a83415d84

commit dc47fdf1319f18be1aadbcdef17c721a83415d84
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2021-03-05 21:19:35 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2021-04-09 20:42:44 +0000

    Stop arming periodic process timers on suspend or terminate
    
    Reported and reviewed by:       markj
    Tested by:      markj, pho
    Sponsored by:   The FreeBSD Foundation
    MFC after:      2 weeks
    Differential revision:  https://reviews.freebsd.org/D29106
---
 sys/kern/kern_sig.c    |  6 ++++--
 sys/kern/kern_time.c   | 38 ++++++++++++++++++++++++++++++++++++--
 sys/kern/sys_process.c |  1 +
 sys/sys/proc.h         |  2 ++
 4 files changed, 43 insertions(+), 4 deletions(-)

diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 3d55405d3151..212b4997dd5e 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -2322,7 +2322,7 @@ tdsendsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
 				thread_unsuspend(p);
 				PROC_SUNLOCK(p);
 				sigqueue_delete(sigqueue, sig);
-				goto out;
+				goto out_cont;
 			}
 			if (action == SIG_CATCH) {
 				/*
@@ -2337,7 +2337,7 @@ tdsendsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi)
 			 */
 			thread_unsuspend(p);
 			PROC_SUNLOCK(p);
-			goto out;
+			goto out_cont;
 		}
 
 		if (prop & SIGPROP_STOP) {
@@ -2422,6 +2422,8 @@ runfast:
 	PROC_SLOCK(p);
 	thread_unsuspend(p);
 	PROC_SUNLOCK(p);
+out_cont:
+	itimer_proc_continue(p);
 out:
 	/* If we jump here, proc slock should not be owned. */
 	PROC_SLOCK_ASSERT(p, MA_NOTOWNED);
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
index 44f6b4ad07f2..3010ee326105 100644
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -881,6 +881,33 @@ kern_setitimer(struct thread *td, u_int which, struct itimerval *aitv,
 	return (0);
 }
 
+static void
+realitexpire_reset_callout(struct proc *p, sbintime_t *isbtp)
+{
+	sbintime_t prec;
+
+	prec = isbtp == NULL ? tvtosbt(p->p_realtimer.it_interval) : *isbtp;
+	callout_reset_sbt(&p->p_itcallout, tvtosbt(p->p_realtimer.it_value),
+	    prec >> tc_precexp, realitexpire, p, C_ABSOLUTE);
+}
+
+void
+itimer_proc_continue(struct proc *p)
+{
+	struct timeval ctv;
+
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+
+	if ((p->p_flag2 & P2_ITSTOPPED) != 0) {
+		p->p_flag2 &= ~P2_ITSTOPPED;
+		microuptime(&ctv);
+		if (timevalcmp(&p->p_realtimer.it_value, &ctv, >=))
+			realitexpire(p);
+		else
+			realitexpire_reset_callout(p, NULL);
+	}
+}
+
 /*
  * Real interval timer expired:
  * send process whose timer expired an alarm signal.
@@ -908,6 +935,7 @@ realitexpire(void *arg)
 			wakeup(&p->p_itcallout);
 		return;
 	}
+
 	isbt = tvtosbt(p->p_realtimer.it_interval);
 	if (isbt >= sbt_timethreshold)
 		getmicrouptime(&ctv);
@@ -917,8 +945,14 @@ realitexpire(void *arg)
 		timevaladd(&p->p_realtimer.it_value,
 		    &p->p_realtimer.it_interval);
 	} while (timevalcmp(&p->p_realtimer.it_value, &ctv, <=));
-	callout_reset_sbt(&p->p_itcallout, tvtosbt(p->p_realtimer.it_value),
-	    isbt >> tc_precexp, realitexpire, p, C_ABSOLUTE);
+
+	if (P_SHOULDSTOP(p) || P_KILLED(p)) {
+		p->p_flag2 |= P2_ITSTOPPED;
+		return;
+	}
+
+	p->p_flag2 &= ~P2_ITSTOPPED;
+	realitexpire_reset_callout(p, &isbt);
 }
 
 /*
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index 3a184f1d678f..8c0f743aef8a 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -1094,6 +1094,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
 		p->p_flag &= ~(P_STOPPED_TRACE | P_STOPPED_SIG | P_WAITED);
 		thread_unsuspend(p);
 		PROC_SUNLOCK(p);
+		itimer_proc_continue(p);
 		break;
 
 	case PT_WRITE_I:
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index d51ad1093833..8d41b9b20f10 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -825,6 +825,7 @@ struct proc {
 						   MAP_STACK */
 #define	P2_STKGAP_DISABLE_EXEC	0x00001000	/* Stack gap disabled
 						   after exec */
+#define	P2_ITSTOPPED		0x00002000
 
 /* Flags protected by proctree_lock, kept in p_treeflags. */
 #define	P_TREE_ORPHANED		0x00000001	/* Reparented, on orphan list */
@@ -1091,6 +1092,7 @@ void	fork_exit(void (*)(void *, struct trapframe *), void *,
 	    struct trapframe *);
 void	fork_return(struct thread *, struct trapframe *);
 int	inferior(struct proc *p);
+void	itimer_proc_continue(struct proc *p);
 void	kern_proc_vmmap_resident(struct vm_map *map, struct vm_map_entry *entry,
 	    int *resident_count, bool *super);
 void	kern_yield(int);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202104092044.139KiWv5070966>