X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fdaemon%2Fcollectd.c;h=8573579166ab7e0aa13078d934ec92ffbf30324e;hb=2761915bed8c6caea41018be3e675aa712cc0b0a;hp=6e625bbb04cdc062f87335a45153523a6cf75c57;hpb=b286b677bb54a3192a4121c2aa0857a133fd0603;p=collectd.git diff --git a/src/daemon/collectd.c b/src/daemon/collectd.c index 6e625bbb..85735791 100644 --- a/src/daemon/collectd.c +++ b/src/daemon/collectd.c @@ -26,18 +26,15 @@ **/ #include "collectd.h" -#include "common.h" +#include "common.h" #include "plugin.h" #include "configfile.h" #include -#include #include #include -#include - #if HAVE_LOCALE_H # include #endif @@ -55,7 +52,6 @@ */ char hostname_g[DATA_MAX_NAME_LEN]; cdtime_t interval_g; -int pidfile_from_cli = 0; int timeout_g; #if HAVE_LIBKSTAT kstat_ctl_t *kc; @@ -101,9 +97,7 @@ static int init_hostname (void) { const char *str; - struct addrinfo ai_hints; struct addrinfo *ai_list; - struct addrinfo *ai_ptr; int status; str = global_option_get ("Hostname"); @@ -124,8 +118,9 @@ static int init_hostname (void) if (IS_FALSE (str)) return (0); - memset (&ai_hints, '\0', sizeof (ai_hints)); - ai_hints.ai_flags = AI_CANONNAME; + struct addrinfo ai_hints = { + .ai_flags = AI_CANONNAME + }; status = getaddrinfo (hostname_g, NULL, &ai_hints, &ai_list); if (status != 0) @@ -138,7 +133,7 @@ static int init_hostname (void) return (-1); } - for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) + for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) { if (ai_ptr->ai_canonname == NULL) continue; @@ -197,7 +192,7 @@ static int change_basedir (const char *orig_dir) while ((dirlen > 0) && (dir[dirlen - 1] == '/')) dir[--dirlen] = '\0'; - if (dirlen <= 0) { + if (dirlen == 0) { free (dir); return (-1); } @@ -270,6 +265,7 @@ static void update_kstat (void) /* TODO * Remove all settings but `-f' and `-C' */ +__attribute__((noreturn)) static void exit_usage (int status) { printf ("Usage: "PACKAGE_NAME" [OPTIONS]\n\n" @@ -332,9 +328,7 @@ static int do_init (void) } #endif - plugin_init_all (); - - return (0); + return plugin_init_all (); } /* int do_init () */ @@ -388,8 +382,7 @@ static int do_loop (void) static int do_shutdown (void) { - plugin_shutdown_all (); - return (0); + return plugin_shutdown_all (); } /* int do_shutdown */ #if COLLECT_DAEMON @@ -425,15 +418,18 @@ static int pidfile_remove (void) #ifdef KERNEL_LINUX static int notify_upstart (void) { - const char *upstart_job = getenv("UPSTART_JOB"); + char const *upstart_job = getenv("UPSTART_JOB"); if (upstart_job == NULL) return 0; if (strcmp(upstart_job, "collectd") != 0) + { + WARNING ("Environment specifies unexpected UPSTART_JOB=\"%s\", expected \"collectd\". Ignoring the variable.", upstart_job); return 0; + } - WARNING ("supervised by upstart, will stop to signal readyness"); + NOTICE("Upstart detected, stopping now to signal readyness."); raise(SIGSTOP); unsetenv("UPSTART_JOB"); @@ -442,49 +438,68 @@ static int notify_upstart (void) static int notify_systemd (void) { - int fd = -1; - const char *notifysocket = getenv("NOTIFY_SOCKET"); - struct sockaddr_un su; - struct iovec iov; - struct msghdr hdr; + int fd; + const char *notifysocket; + struct sockaddr_un su = { 0 }; + size_t su_size; + char buffer[] = "READY=1\n"; + notifysocket = getenv ("NOTIFY_SOCKET"); if (notifysocket == NULL) return 0; - if ((strchr("@/", notifysocket[0])) == NULL || - strlen(notifysocket) < 2) + if ((strlen (notifysocket) < 2) + || ((notifysocket[0] != '@') && (notifysocket[0] != '/'))) + { + ERROR ("invalid notification socket NOTIFY_SOCKET=\"%s\": path must be absolute", notifysocket); return 0; + } + NOTICE ("Systemd detected, trying to signal readyness."); - WARNING ("supervised by systemd, will signal readyness"); - if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { - WARNING ("cannot contact systemd socket %s", notifysocket); + unsetenv ("NOTIFY_SOCKET"); + +#if defined(SOCK_CLOEXEC) + fd = socket (AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, /* protocol = */ 0); +#else + fd = socket (AF_UNIX, SOCK_DGRAM, /* protocol = */ 0); +#endif + if (fd < 0) { + char errbuf[1024]; + ERROR ("creating UNIX socket failed: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); return 0; } - bzero(&su, sizeof(su)); su.sun_family = AF_UNIX; - sstrncpy (su.sun_path, notifysocket, sizeof(su.sun_path)); - - if (notifysocket[0] == '@') + if (notifysocket[0] != '@') + { + /* regular UNIX socket */ + sstrncpy (su.sun_path, notifysocket, sizeof (su.sun_path)); + su_size = sizeof (su); + } + else + { + /* Linux abstract namespace socket: specify address as "\0foo", i.e. + * start with a null byte. Since null bytes have no special meaning in + * that case, we have to set su_size correctly to cover only the bytes + * that are part of the address. */ + sstrncpy (su.sun_path, notifysocket, sizeof (su.sun_path)); su.sun_path[0] = 0; + su_size = sizeof (sa_family_t) + strlen (notifysocket); + if (su_size > sizeof (su)) + su_size = sizeof (su); + } - bzero(&iov, sizeof(iov)); - iov.iov_base = "READY=1"; - iov.iov_len = strlen("READY=1"); - - bzero(&hdr, sizeof(hdr)); - hdr.msg_name = &su; - hdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + - strlen(notifysocket); - hdr.msg_iov = &iov; - hdr.msg_iovlen = 1; - - unsetenv("NOTIFY_SOCKET"); - if (sendmsg(fd, &hdr, MSG_NOSIGNAL) < 0) { - WARNING ("cannot send notification to systemd"); + if (sendto (fd, buffer, strlen (buffer), MSG_NOSIGNAL, (void *) &su, (socklen_t) su_size) < 0) + { + char errbuf[1024]; + ERROR ("sendto(\"%s\") failed: %s", notifysocket, + sstrerror (errno, errbuf, sizeof (errbuf))); close(fd); return 0; } + + unsetenv ("NOTIFY_SOCKET"); close(fd); return 1; } @@ -492,16 +507,11 @@ static int notify_systemd (void) int main (int argc, char **argv) { - struct sigaction sig_int_action; - struct sigaction sig_term_action; - struct sigaction sig_usr1_action; - struct sigaction sig_pipe_action; - char *configfile = CONFIGFILE; + const char *configfile = CONFIGFILE; int test_config = 0; int test_readall = 0; const char *basedir; #if COLLECT_DAEMON - struct sigaction sig_chld_action; pid_t pid; int daemonize = 1; #endif @@ -531,15 +541,14 @@ int main (int argc, char **argv) break; case 'T': test_readall = 1; - global_option_set ("ReadThreads", "-1"); + global_option_set ("ReadThreads", "-1", 1); #if COLLECT_DAEMON daemonize = 0; #endif /* COLLECT_DAEMON */ break; #if COLLECT_DAEMON case 'P': - global_option_set ("PIDFile", optarg); - pidfile_from_cli = 1; + global_option_set ("PIDFile", optarg, 1); break; case 'f': daemonize = 0; @@ -602,8 +611,10 @@ int main (int argc, char **argv) /* * fork off child */ - memset (&sig_chld_action, '\0', sizeof (sig_chld_action)); - sig_chld_action.sa_handler = SIG_IGN; + struct sigaction sig_chld_action = { + .sa_handler = SIG_IGN + }; + sigaction (SIGCHLD, &sig_chld_action, NULL); /* @@ -616,6 +627,8 @@ int main (int argc, char **argv) #endif ) { + int status; + if ((pid = fork ()) == -1) { /* error */ @@ -644,33 +657,42 @@ int main (int argc, char **argv) close (1); close (0); - if (open ("/dev/null", O_RDWR) != 0) + status = open ("/dev/null", O_RDWR); + if (status != 0) { - ERROR ("Error: Could not connect `STDIN' to `/dev/null'"); + ERROR ("Error: Could not connect `STDIN' to `/dev/null' (status %d)", status); return (1); } - if (dup (0) != 1) + + status = dup (0); + if (status != 1) { - ERROR ("Error: Could not connect `STDOUT' to `/dev/null'"); + ERROR ("Error: Could not connect `STDOUT' to `/dev/null' (status %d)", status); return (1); } - if (dup (0) != 2) + + status = dup (0); + if (status != 2) { - ERROR ("Error: Could not connect `STDERR' to `/dev/null'"); + ERROR ("Error: Could not connect `STDERR' to `/dev/null', (status %d)", status); return (1); } } /* if (daemonize) */ #endif /* COLLECT_DAEMON */ - memset (&sig_pipe_action, '\0', sizeof (sig_pipe_action)); - sig_pipe_action.sa_handler = SIG_IGN; + struct sigaction sig_pipe_action = { + .sa_handler = SIG_IGN + }; + sigaction (SIGPIPE, &sig_pipe_action, NULL); /* * install signal handlers */ - memset (&sig_int_action, '\0', sizeof (sig_int_action)); - sig_int_action.sa_handler = sig_int_handler; + struct sigaction sig_int_action = { + .sa_handler = sig_int_handler + }; + if (0 != sigaction (SIGINT, &sig_int_action, NULL)) { char errbuf[1024]; ERROR ("Error: Failed to install a signal handler for signal INT: %s", @@ -678,8 +700,10 @@ int main (int argc, char **argv) return (1); } - memset (&sig_term_action, '\0', sizeof (sig_term_action)); - sig_term_action.sa_handler = sig_term_handler; + struct sigaction sig_term_action = { + .sa_handler = sig_term_handler + }; + if (0 != sigaction (SIGTERM, &sig_term_action, NULL)) { char errbuf[1024]; ERROR ("Error: Failed to install a signal handler for signal TERM: %s", @@ -687,8 +711,10 @@ int main (int argc, char **argv) return (1); } - memset (&sig_usr1_action, '\0', sizeof (sig_usr1_action)); - sig_usr1_action.sa_handler = sig_usr1_handler; + struct sigaction sig_usr1_action = { + .sa_handler = sig_usr1_handler + }; + if (0 != sigaction (SIGUSR1, &sig_usr1_action, NULL)) { char errbuf[1024]; ERROR ("Error: Failed to install a signal handler for signal USR1: %s", @@ -699,12 +725,19 @@ int main (int argc, char **argv) /* * run the actual loops */ - do_init (); + if (do_init () != 0) + { + ERROR ("Error: one or more plugin init callbacks failed."); + exit_status = 1; + } if (test_readall) { if (plugin_read_all_once () != 0) + { + ERROR ("Error: one or more plugin read callbacks failed."); exit_status = 1; + } } else { @@ -715,7 +748,11 @@ int main (int argc, char **argv) /* close syslog */ INFO ("Exiting normally."); - do_shutdown (); + if (do_shutdown () != 0) + { + ERROR ("Error: one or more plugin shutdown callbacks failed."); + exit_status = 1; + } #if COLLECT_DAEMON if (daemonize)