From: Florian Forster Date: Fri, 24 Nov 2023 22:31:03 +0000 (+0100) Subject: Notify upstart/systemd after initialization is complete. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F4164%2Fhead;p=thirdparty%2Fcollectd.git Notify upstart/systemd after initialization is complete. Fixes: #4152 --- diff --git a/src/daemon/cmd.c b/src/daemon/cmd.c index 09aee6abb..4ca0cbab3 100644 --- a/src/daemon/cmd.c +++ b/src/daemon/cmd.c @@ -83,42 +83,45 @@ static int pidfile_remove(void) { #endif /* COLLECT_DAEMON */ #ifdef KERNEL_LINUX -static int notify_upstart(void) { +static bool using_upstart(void) { char const *upstart_job = getenv("UPSTART_JOB"); - if (upstart_job == NULL) - return 0; + return false; if (strcmp(upstart_job, "collectd") != 0) { WARNING("Environment specifies unexpected UPSTART_JOB=\"%s\", expected " "\"collectd\". Ignoring the variable.", upstart_job); - return 0; + return false; } + return true; +} + +static void notify_upstart(void) { NOTICE("Upstart detected, stopping now to signal readiness."); raise(SIGSTOP); unsetenv("UPSTART_JOB"); - - return 1; } -static int notify_systemd(void) { - size_t su_size; +static bool using_systemd(void) { const char *notifysocket = getenv("NOTIFY_SOCKET"); if (notifysocket == NULL) - return 0; + return false; if ((strlen(notifysocket) < 2) || ((notifysocket[0] != '@') && (notifysocket[0] != '/'))) { ERROR("invalid notification socket NOTIFY_SOCKET=\"%s\": path must be " "absolute", notifysocket); - return 0; + return false; } - NOTICE("Systemd detected, trying to signal readiness."); - unsetenv("NOTIFY_SOCKET"); + return true; +} + +static void notify_systemd(void) { + NOTICE("Systemd detected, trying to signal readiness."); int fd; #if defined(SOCK_CLOEXEC) @@ -128,11 +131,15 @@ static int notify_systemd(void) { #endif if (fd < 0) { ERROR("creating UNIX socket failed: %s", STRERRNO); - return 0; + return; } - struct sockaddr_un su = {0}; - su.sun_family = AF_UNIX; + struct sockaddr_un su = { + .sun_family = AF_UNIX, + }; + + const char *notifysocket = getenv("NOTIFY_SOCKET"); + size_t su_size = 0; if (notifysocket[0] != '@') { /* regular UNIX socket */ sstrncpy(su.sun_path, notifysocket, sizeof(su.sun_path)); @@ -154,12 +161,11 @@ static int notify_systemd(void) { (socklen_t)su_size) < 0) { ERROR("sendto(\"%s\") failed: %s", notifysocket, STRERRNO); close(fd); - return 0; + return; } unsetenv("NOTIFY_SOCKET"); close(fd); - return 1; } #endif /* KERNEL_LINUX */ @@ -178,11 +184,13 @@ int main(int argc, char **argv) { * Only daemonize if we're not being supervised * by upstart or systemd (when using Linux). */ - if (config.daemonize #ifdef KERNEL_LINUX - && notify_upstart() == 0 && notify_systemd() == 0 + if (using_upstart() || using_systemd()) { + config.daemonize = false; + } #endif - ) { + + if (config.daemonize) { pid_t pid; if ((pid = fork()) == -1) { /* error */ @@ -260,7 +268,16 @@ int main(int argc, char **argv) { return 1; } - int exit_status = run_loop(config.test_readall); + void (*notify_func)(void) = NULL; +#ifdef KERNEL_LINUX + if (using_upstart()) { + notify_func = notify_upstart; + } else if (using_systemd()) { + notify_func = notify_systemd; + } +#endif + + int exit_status = run_loop(config.test_readall, notify_func); #if COLLECT_DAEMON if (config.daemonize) diff --git a/src/daemon/cmd.h b/src/daemon/cmd.h index 152ee63e3..97ddacc9b 100644 --- a/src/daemon/cmd.h +++ b/src/daemon/cmd.h @@ -36,6 +36,6 @@ struct cmdline_config { void stop_collectd(void); struct cmdline_config init_config(int argc, char **argv); -int run_loop(bool test_readall); +int run_loop(bool test_readall, void (*notify_func)(void)); #endif /* CMD_H */ diff --git a/src/daemon/collectd.c b/src/daemon/collectd.c index cad82d4d5..7e5081130 100644 --- a/src/daemon/collectd.c +++ b/src/daemon/collectd.c @@ -409,7 +409,7 @@ struct cmdline_config init_config(int argc, char **argv) { return config; } -int run_loop(bool test_readall) { +int run_loop(bool test_readall, void (*notify_func)(void)) { int exit_status = 0; if (do_init() != 0) { @@ -423,6 +423,10 @@ int run_loop(bool test_readall) { exit_status = 1; } } else { + if (notify_func != NULL) { + /* notify upstart or systemd that initialization has completed. */ + notify_func(); + } INFO("Initialization complete, entering read-loop."); do_loop(); }