git: 99c5c0cb1556 - stable/14 - dhclient: Switch timeouts from time_t to timespec

From: Colin Percival <cperciva_at_FreeBSD.org>
Date: Tue, 20 Aug 2024 04:58:15 UTC
The branch stable/14 has been updated by cperciva:

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

commit 99c5c0cb1556daf2818e99a934dc6a2f99fa30f9
Author:     Isaac Cilia Attard <icattard@FreeBSD.org>
AuthorDate: 2024-07-08 05:43:09 +0000
Commit:     Colin Percival <cperciva@FreeBSD.org>
CommitDate: 2024-08-20 04:57:08 +0000

    dhclient: Switch timeouts from time_t to timespec
    
    Introduce a new function, add_timeout_timespec(), to use timespec
    structs to handle timeouts. Make add_timeout() into a wrapper for the
    latter function to retain compatibility with the rest of the codebase.
    No functional change intended.
    
    Sponsored by:   Google LLC (GSoC 2024)
    Signed-off-by:  Isaac Cilia Attard <icattard@FreeBSD.org>
    MFC after:      10 days
    Reviwed by:     cperciva, brooks, Tom Hukins, Alexander Ziaee
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/1368
    
    (cherry picked from commit 16a235f23c066d27b3a53c66cf6aa329be07cdb9)
---
 sbin/dhclient/dhcpd.h    |  3 ++-
 sbin/dhclient/dispatch.c | 28 +++++++++++++++++++---------
 2 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h
index 399b5c1ecf6c..56a38d733501 100644
--- a/sbin/dhclient/dhcpd.h
+++ b/sbin/dhclient/dhcpd.h
@@ -219,7 +219,7 @@ struct interface_info {
 
 struct timeout {
 	struct timeout	*next;
-	time_t		 when;
+	struct timespec	 when;
 	void		 (*func)(void *);
 	void		*what;
 };
@@ -321,6 +321,7 @@ void reinitialize_interfaces(void);
 void dispatch(void);
 void got_one(struct protocol *);
 void add_timeout(time_t, void (*)(void *), void *);
+void add_timeout_timespec(struct timespec, void (*)(void *), void *);
 void cancel_timeout(void (*)(void *), void *);
 void add_protocol(const char *, int, void (*)(struct protocol *), void *);
 void remove_protocol(struct protocol *);
diff --git a/sbin/dhclient/dispatch.c b/sbin/dhclient/dispatch.c
index 310f477f8a4f..aa15c35a9f15 100644
--- a/sbin/dhclient/dispatch.c
+++ b/sbin/dhclient/dispatch.c
@@ -155,7 +155,8 @@ dispatch(void)
 	int count, live_interfaces, i, to_msec, nfds = 0;
 	struct protocol *l;
 	struct pollfd *fds;
-	time_t howlong;
+	struct timespec howlong;
+	struct timespec time_now = { .tv_sec = cur_time, .tv_nsec = 0 };
 
 	for (l = protocols; l; l = l->next)
 		nfds++;
@@ -173,7 +174,7 @@ another:
 		if (timeouts) {
 			struct timeout *t;
 
-			if (timeouts->when <= cur_time) {
+			if (timespeccmp(&timeouts->when, &time_now, <=)) {
 				t = timeouts;
 				timeouts = timeouts->next;
 				(*(t->func))(t->what);
@@ -188,10 +189,10 @@ another:
 			 * int for poll, while not polling with a
 			 * negative timeout and blocking indefinitely.
 			 */
-			howlong = timeouts->when - cur_time;
-			if (howlong > INT_MAX / 1000)
-				howlong = INT_MAX / 1000;
-			to_msec = howlong * 1000;
+			timespecsub(&timeouts->when, &time_now, &howlong);
+			if (howlong.tv_sec > INT_MAX / 1000)
+				howlong.tv_sec = INT_MAX / 1000;
+			to_msec = howlong.tv_sec * 1000;
 		} else
 			to_msec = -1;
 
@@ -219,6 +220,7 @@ another:
 		if (count == -1) {
 			if (errno == EAGAIN || errno == EINTR) {
 				time(&cur_time);
+				time_now.tv_sec = cur_time;
 				continue;
 			} else
 				error("poll: %m");
@@ -226,6 +228,7 @@ another:
 
 		/* Get the current time... */
 		time(&cur_time);
+		time_now.tv_sec = cur_time;
 
 		i = 0;
 		for (l = protocols; l; l = l->next) {
@@ -356,7 +359,14 @@ active:
 }
 
 void
-add_timeout(time_t when, void (*where)(void *), void *what)
+add_timeout(time_t when_s, void (*where)(void *), void *what)
+{
+	struct timespec when = { .tv_sec = when_s, .tv_nsec = 0 };
+	add_timeout_timespec(when, where, what);
+}
+
+void
+add_timeout_timespec(struct timespec when, void (*where)(void *), void *what)
 {
 	struct timeout *t, *q;
 
@@ -395,7 +405,7 @@ add_timeout(time_t when, void (*where)(void *), void *what)
 	/* Now sort this timeout into the timeout list. */
 
 	/* Beginning of list? */
-	if (!timeouts || timeouts->when > q->when) {
+	if (!timeouts || timespeccmp(&timeouts->when, &q->when, >)) {
 		q->next = timeouts;
 		timeouts = q;
 		return;
@@ -403,7 +413,7 @@ add_timeout(time_t when, void (*where)(void *), void *what)
 
 	/* Middle of list? */
 	for (t = timeouts; t->next; t = t->next) {
-		if (t->next->when > q->when) {
+		if (timespeccmp(&t->next->when, &q->when, >)) {
 			q->next = t->next;
 			t->next = q;
 			return;