From 7cb09b220dbf6381dd6edd24725c5e1ff5dce5b2 Mon Sep 17 00:00:00 2001 From: Quentin Armitage Date: Sat, 10 Aug 2024 15:52:58 +0100 Subject: [PATCH] all: Ensure pid file exists when respawning child process If a child process is respawned, the old pidfile may or may not still exist. If it doesn't exist, we need to recreate it. If it still exists we need to reset our file offset and truncate the file before re-wrighting it. --- keepalived/core/main.c | 3 ++ keepalived/core/pidfile.c | 65 ++++++++++++++++++++++++++++-------- keepalived/include/main.h | 1 + keepalived/include/pidfile.h | 2 +- 4 files changed, 57 insertions(+), 14 deletions(-) diff --git a/keepalived/core/main.c b/keepalived/core/main.c index 703b89b425..9f34d99990 100644 --- a/keepalived/core/main.c +++ b/keepalived/core/main.c @@ -169,6 +169,7 @@ const char *snmp_socket; /* Socket to use for SNMP agent */ #endif static const char *syslog_ident; /* syslog ident if not default */ bool use_pid_dir; /* Put pid files in /run/keepalived or @localstatedir@/run/keepalived */ +bool children_started; /* Set once children have been run first time */ unsigned os_major; /* Kernel version */ unsigned os_minor; @@ -560,6 +561,8 @@ start_keepalived(__attribute__((unused)) thread_ref_t thread) pidfile_rm(&bfd_pidfile); #endif + children_started = true; + #ifndef _ONE_PROCESS_DEBUG_ /* Do we have a reload file to monitor */ if (global_data->reload_time_file) diff --git a/keepalived/core/pidfile.c b/keepalived/core/pidfile.c index cf49aee98f..8e2214d86d 100644 --- a/keepalived/core/pidfile.c +++ b/keepalived/core/pidfile.c @@ -151,18 +151,6 @@ close_other_pidfiles(void) #endif } -/* Create the running daemon pidfile */ -bool -pidfile_write(const pidfile_t *pidf) -{ - if (pidf->fd == -1) - return false; - - dprintf(pidf->fd, "%d\n", getpid()); - - return true; -} - /* return the daemon running state */ static bool create_pidfile(pidfile_t *pidf) @@ -226,7 +214,7 @@ create_pidfile(pidfile_t *pidf) break; } - /* pid file is now openned, locked and 0 length */ + /* pid file is now opened, locked and 0 length */ return false; } @@ -258,3 +246,54 @@ keepalived_running(unsigned long mode) #endif return false; } + +/* Create the running daemon pidfile */ +bool +pidfile_write(pidfile_t *pidf) +{ + int ret; + + if (pidf->fd == -1) + return false; + + if (children_started) { + struct stat statb, fstatb; + + /* There could be more error handling, but that will just + * complicate the code for minimal benefit. */ + if (stat(pidf->path, &statb)) { + /* pidfile no longer exists */ + close(pidf->fd); + create_pidfile(pidf); + } else { + if (fstat(pidf->fd, &fstatb) || + statb.st_dev != fstatb.st_dev || + statb.st_ino != fstatb.st_ino) { + /* The pidfile has been deleted and recreated. Open the new one. */ + close(pidf->fd); + while ((pidf->fd = open(pidf->path, O_NOFOLLOW | O_WRONLY | O_NONBLOCK)) == -1 && errno == EINTR); + + if (pidf->fd == -1) + return false; + } + + /* Since we have already written to the pid file, + * we need to reset the file offset and truncate the file. */ + off_t offs = lseek(pidf->fd, 0, SEEK_CUR); + if (offs) { + lseek(pidf->fd, 0, SEEK_SET); + if (ftruncate(pidf->fd, 0)) + log_message(LOG_INFO, "ftruncate error %d - %m", errno); + } + } + } + + ret = dprintf(pidf->fd, "%d\n", getpid()); + + if (ret < 0) + log_message(LOG_INFO, "pidfile_write returned %d, errno %d - %m", ret, errno); + else + log_message(LOG_INFO, "pidfile_write returned %d", ret); + + return true; +} diff --git a/keepalived/include/main.h b/keepalived/include/main.h index b0c6bd49b7..14caac0cf9 100644 --- a/keepalived/include/main.h +++ b/keepalived/include/main.h @@ -79,6 +79,7 @@ extern bool snmp_option; /* Enable SNMP support */ extern const char *snmp_socket; /* Socket to use for SNMP agent */ #endif extern bool use_pid_dir; /* pid files in /run/keepalived */ +extern bool children_started; /* Set once children have been run first time */ extern unsigned os_major; /* Kernel version */ extern unsigned os_minor; extern unsigned os_release; diff --git a/keepalived/include/pidfile.h b/keepalived/include/pidfile.h index 068a1db983..b8b595f984 100644 --- a/keepalived/include/pidfile.h +++ b/keepalived/include/pidfile.h @@ -58,7 +58,7 @@ extern void create_pid_dir(void); extern void remove_pid_dir(void); extern char *make_pidfile_name(const char *, const char *, const char *); extern void pidfile_close(pidfile_t *, bool); -extern bool pidfile_write(const pidfile_t *); +extern bool pidfile_write(pidfile_t *); extern void pidfile_rm(pidfile_t *); extern void close_other_pidfiles(void); extern bool keepalived_running(unsigned long);