From 7b5c03f9dec9e3f87f420e6f9df31c7e70d0422e Mon Sep 17 00:00:00 2001 From: Quentin Armitage Date: Tue, 19 Mar 2024 17:37:22 +0000 Subject: [PATCH] core: make startup/shutdown scripts work when not using --dont-fork check_start_stop_script_secure() checks that the parent process has not changed while it is doing its checks, so we need to set the pid of the parent process (main_pid) before calling the function. There is a further complication that called getppid() too soon after a fork() with the parent process exiting after the fork means that we don't get the pid of the new parent, so we need to loop until getppid() returns a diffweent pid. Signed-off-by: Quentin Armitage --- keepalived/core/main.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/keepalived/core/main.c b/keepalived/core/main.c index 7fae7f79d3..4628e5e2ba 100644 --- a/keepalived/core/main.c +++ b/keepalived/core/main.c @@ -2781,12 +2781,26 @@ keepalived_main(int argc, char **argv) } /* daemonize process */ - if (!__test_bit(DONT_FORK_BIT, &debug) && xdaemon() > 0) { - closelog(); - FREE_CONST_PTR(config_id); - FREE_PTR(orig_core_dump_pattern); - close_std_fd(); - exit(0); + if (!__test_bit(DONT_FORK_BIT, &debug)) { + pid_t old_ppid = getpid(); + + if (xdaemon() > 0) { + /* Parent process */ + closelog(); + FREE_CONST_PTR(config_id); + FREE_PTR(orig_core_dump_pattern); + close_std_fd(); + exit(0); + } + + /* Child process */ + + /* check_start_stop_script_secure() called below makes a check + * that our parent process hasn't changed, but it can take a while + * for the parent of the fork to exit which is when our parent pid + * changes. We need to loop until that has happened. */ + while (old_ppid == getppid()) + usleep(10); } #ifdef _MEM_CHECK_ @@ -2794,6 +2808,9 @@ keepalived_main(int argc, char **argv) #endif if (global_data->startup_script || global_data->shutdown_script) { + /* This is a workaround for the check in check_start_stop_script_secure() */ + main_pid = getppid(); + magic = ka_magic_open(); script_flags = 0; if (global_data->startup_script)