git: aa8722cc18e4 - main - daemon: truncate the pidfile when we're waiting to restart child

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Tue, 19 Nov 2024 19:51:41 UTC
The branch main has been updated by kevans:

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

commit aa8722cc18e4620ea5e7b0a4917207ed1508393d
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2024-11-19 19:51:26 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2024-11-19 19:51:26 +0000

    daemon: truncate the pidfile when we're waiting to restart child
    
    We need to be able to test some more restart behavior that depends on
    knowing specifically where we're at (inside the event loop or outside of
    the event loop).  Truncate the pidfile until the process is restarted to
    give the test a clean marker rather than having to add arbitrary delays
    and hoping for the best.
    
    Reviewed by:    des, markj
    Differential Revision:  https://reviews.freebsd.org/D47003
---
 usr.sbin/daemon/daemon.c             | 30 ++++++++++++++++++++++++++++++
 usr.sbin/daemon/tests/daemon_test.sh |  7 +++++--
 2 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/usr.sbin/daemon/daemon.c b/usr.sbin/daemon/daemon.c
index 7214faf8bde3..a21346086dd1 100644
--- a/usr.sbin/daemon/daemon.c
+++ b/usr.sbin/daemon/daemon.c
@@ -114,6 +114,8 @@ static void daemon_exec(struct daemon_state *);
 static bool daemon_is_child_dead(struct daemon_state *);
 static void daemon_set_child_pipe(struct daemon_state *);
 
+static int pidfile_truncate(struct pidfh *);
+
 static const char shortopts[] = "+cfHSp:P:ru:o:s:l:t:m:R:T:C:h";
 
 static const struct option longopts[] = {
@@ -526,6 +528,15 @@ daemon_eventloop(struct daemon_state *state)
 	close(kq);
 	close(state->pipe_rd);
 	state->pipe_rd = -1;
+
+	/*
+	 * We don't have to truncate the pidfile, but it's easier to test
+	 * daemon(8) behavior in some respects if we do.  We won't bother if
+	 * the child won't be restarted.
+	 */
+	if (state->child_pidfh != NULL && state->restart_enabled) {
+		pidfile_truncate(state->child_pidfh);
+	}
 }
 
 static void
@@ -823,3 +834,22 @@ daemon_set_child_pipe(struct daemon_state *state)
 	/* The child gets dup'd pipes. */
 	close(state->pipe_rd);
 }
+
+static int
+pidfile_truncate(struct pidfh *pfh)
+{
+	int pfd = pidfile_fileno(pfh);
+
+	assert(pfd >= 0);
+
+	if (ftruncate(pfd, 0) == -1)
+		return (-1);
+
+	/*
+	 * pidfile_write(3) will always pwrite(..., 0) today, but let's assume
+	 * it may not always and do a best-effort reset of the position just to
+	 * set a good example.
+	 */
+	(void)lseek(pfd, 0, SEEK_SET);
+	return (0);
+}
diff --git a/usr.sbin/daemon/tests/daemon_test.sh b/usr.sbin/daemon/tests/daemon_test.sh
index 948a9f6a8a57..2ad0803842b7 100644
--- a/usr.sbin/daemon/tests/daemon_test.sh
+++ b/usr.sbin/daemon/tests/daemon_test.sh
@@ -139,8 +139,11 @@ restart_child_body() {
 	kill $orig_sleep_pid
 	# Wait up to 10s for the daemon to restart the child.
 	for t in `seq 0 0.1 10`; do
-		new_sleep_pid=`cat sleep.pid`
-		[ "$orig_sleep_pid" -ne "$new_sleep_pid" ] && break
+		if [ -s "sleep.pid" ]; then
+			new_sleep_pid=`cat sleep.pid`
+			[ "$orig_sleep_pid" -ne "$new_sleep_pid" ] && break
+		fi
+
 		sleep 0.1
 	done
 	[ "$orig_sleep_pid" -ne "$new_sleep_pid" ] || \