From cb9a8fdbaef4a642eeb84ac9feaf636720d18360 Mon Sep 17 00:00:00 2001
From: William Lallemand <wlallemand@haproxy.org>
Date: Fri, 17 Feb 2023 16:23:52 +0100
Subject: [PATCH] BUG/MINOR: mworker: prevent incorrect values in uptime

Since the recent changes on the clocks, now.tv_sec is not to be used
between processes because it's a clock which is local to the process and
does not contain a real unix timestamp.  This patch fixes the issue by
using "data.tv_sec" which is the wall clock instead of "now.tv_sec'.
It prevents having incoherent timestamps.

It also introduces some checks on negatives values in order to never
displays a netative value if it was computed from a wrong value set by a
previous haproxy version.

It must be backported as far as 2.0.

(cherry picked from commit 5a7f83af84d2a08f69ce1629c7609c98f43411ab)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 7b8337e0cbaeebec26eab0062f0706f9388e3e2c)
Signed-off-by: Willy Tarreau <w@1wt.eu>

Conflict: NA
Reference: https://git.haproxy.org/?p=haproxy-2.6.git;a=commit;h=cb9a8fdbaef4a642eeb84ac9feaf636720d18360
---
 src/haproxy.c |  2 +-
 src/mworker.c | 21 ++++++++++++++++-----
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/src/haproxy.c b/src/haproxy.c
index 5a3f6c755..0cb0662d2 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -3432,7 +3432,7 @@ int main(int argc, char **argv)
 						if (child->reloads == 0 &&
 						    child->options & PROC_O_TYPE_WORKER &&
 						    child->pid == -1) {
-							child->timestamp = now.tv_sec;
+							child->timestamp = date.tv_sec;
 							child->pid = ret;
 							child->version = strdup(haproxy_version);
 							break;
diff --git a/src/mworker.c b/src/mworker.c
index 686fc755d..26b16cca4 100644
--- a/src/mworker.c
+++ b/src/mworker.c
@@ -559,13 +559,16 @@ static int cli_io_handler_show_proc(struct appctx *appctx)
 	struct stconn *sc = appctx_sc(appctx);
 	struct mworker_proc *child;
 	int old = 0;
-	int up = now.tv_sec - proc_self->timestamp;
+	int up = date.tv_sec - proc_self->timestamp;
 	char *uptime = NULL;
 	char *reloadtxt = NULL;
 
 	if (unlikely(sc_ic(sc)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
 		return 1;
 
+	if (up < 0) /* must never be negative because of clock drift */
+		up = 0;
+
 	chunk_reset(&trash);
 
 	memprintf(&reloadtxt, "%d [failed: %d]", proc_self->reloads, proc_self->failedreloads);
@@ -579,7 +582,9 @@ static int cli_io_handler_show_proc(struct appctx *appctx)
 
 	chunk_appendf(&trash, "# workers\n");
 	list_for_each_entry(child, &proc_list, list) {
-		up = now.tv_sec - child->timestamp;
+		up = date.tv_sec - child->timestamp;
+		if (up < 0) /* must never be negative because of clock drift */
+			up = 0;
 
 		if (!(child->options & PROC_O_TYPE_WORKER))
 			continue;
@@ -600,7 +605,9 @@ static int cli_io_handler_show_proc(struct appctx *appctx)
 
 		chunk_appendf(&trash, "# old workers\n");
 		list_for_each_entry(child, &proc_list, list) {
-			up = now.tv_sec - child->timestamp;
+			up = date.tv_sec - child->timestamp;
+			if (up <= 0) /* must never be negative because of clock drift */
+				up = 0;
 
 			if (!(child->options & PROC_O_TYPE_WORKER))
 				continue;
@@ -618,7 +625,9 @@ static int cli_io_handler_show_proc(struct appctx *appctx)
 	chunk_appendf(&trash, "# programs\n");
 	old = 0;
 	list_for_each_entry(child, &proc_list, list) {
-		up = now.tv_sec - child->timestamp;
+		up = date.tv_sec - child->timestamp;
+		if (up < 0) /* must never be negative because of clock drift */
+			up = 0;
 
 		if (!(child->options & PROC_O_TYPE_PROG))
 			continue;
@@ -635,7 +644,9 @@ static int cli_io_handler_show_proc(struct appctx *appctx)
 	if (old) {
 		chunk_appendf(&trash, "# old programs\n");
 		list_for_each_entry(child, &proc_list, list) {
-			up = now.tv_sec - child->timestamp;
+			up = date.tv_sec - child->timestamp;
+			if (up < 0) /* must never be negative because of clock drift */
+				up = 0;
 
 			if (!(child->options & PROC_O_TYPE_PROG))
 				continue;
-- 
2.33.0

