X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Fdaemon%2Fcollectd.c;h=78d410cadb8214dcb6315f2e257ef8dbc9b6a189;hp=d15bb33404a4c7ca200b18602a67c5fa5331c262;hb=54619dc85fd308b21ed09a0271e5c7383c7921b9;hpb=ec51ddee94fa2ba1e01fe0e336ccc9c190a198ff diff --git a/src/daemon/collectd.c b/src/daemon/collectd.c index d15bb334..78d410ca 100644 --- a/src/daemon/collectd.c +++ b/src/daemon/collectd.c @@ -25,15 +25,15 @@ * Alvaro Barcellos **/ +#include "cmd.h" #include "collectd.h" -#include "common.h" #include "configfile.h" #include "plugin.h" +#include "utils/common/common.h" #include #include -#include #if HAVE_LOCALE_H #include @@ -51,45 +51,31 @@ #define COLLECTD_LOCALE "C" #endif -static int loop; - -static void *do_flush(void __attribute__((unused)) * arg) { - INFO("Flushing all data."); - plugin_flush(/* plugin = */ NULL, - /* timeout = */ 0, - /* ident = */ NULL); - INFO("Finished flushing all data."); - pthread_exit(NULL); - return NULL; -} - -static void sig_int_handler(int __attribute__((unused)) signal) { loop++; } - -static void sig_term_handler(int __attribute__((unused)) signal) { loop++; } - -static void sig_usr1_handler(int __attribute__((unused)) signal) { - pthread_t thread; - pthread_attr_t attr; +#ifdef WIN32 +#undef COLLECT_DAEMON +#include +#undef gethostname +#include +#include +#endif - /* flushing the data might take a while, - * so it should be done asynchronously */ - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&thread, &attr, do_flush, NULL); - pthread_attr_destroy(&attr); -} +static int loop; static int init_hostname(void) { const char *str = global_option_get("Hostname"); - if ((str != NULL) && (str[0] != 0)) { + if (str && str[0] != '\0') { hostname_set(str); return 0; } +#ifdef WIN32 + long hostname_len = NI_MAXHOST; +#else long hostname_len = sysconf(_SC_HOST_NAME_MAX); if (hostname_len == -1) { hostname_len = NI_MAXHOST; } +#endif /* WIN32 */ char hostname[hostname_len]; if (gethostname(hostname, hostname_len) != 0) { @@ -118,8 +104,7 @@ static int init_hostname(void) { return -1; } - for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; - ai_ptr = ai_ptr->ai_next) { + for (struct addrinfo *ai_ptr = ai_list; ai_ptr; ai_ptr = ai_ptr->ai_next) { if (ai_ptr->ai_canonname == NULL) continue; @@ -132,13 +117,11 @@ static int init_hostname(void) { } /* int init_hostname */ static int init_global_variables(void) { - char const *str; - interval_g = cf_get_default_interval(); assert(interval_g > 0); DEBUG("interval_g = %.3f;", CDTIME_T_TO_DOUBLE(interval_g)); - str = global_option_get("Timeout"); + const char *str = global_option_get("Timeout"); if (str == NULL) str = "2"; timeout_g = atoi(str); @@ -157,17 +140,13 @@ static int init_global_variables(void) { } /* int init_global_variables */ static int change_basedir(const char *orig_dir, bool create) { - char *dir; - size_t dirlen; - int status; - - dir = strdup(orig_dir); + char *dir = strdup(orig_dir); if (dir == NULL) { ERROR("strdup failed: %s", STRERRNO); return -1; } - dirlen = strlen(dir); + size_t dirlen = strlen(dir); while ((dirlen > 0) && (dir[dirlen - 1] == '/')) dir[--dirlen] = '\0'; @@ -176,7 +155,7 @@ static int change_basedir(const char *orig_dir, bool create) { return -1; } - status = chdir(dir); + int status = chdir(dir); if (status == 0) { free(dir); return 0; @@ -211,8 +190,7 @@ static void update_kstat(void) { if ((kc = kstat_open()) == NULL) ERROR("Unable to open kstat control structure"); } else { - kid_t kid; - kid = kstat_chain_update(kc); + kid_t kid = kstat_chain_update(kc); if (kid > 0) { INFO("kstat chain has been updated"); plugin_init_all(); @@ -225,9 +203,6 @@ static void update_kstat(void) { } /* static void update_kstat (void) */ #endif /* HAVE_LIBKSTAT */ -/* TODO - * Remove all settings but `-f' and `-C' - */ __attribute__((noreturn)) static void exit_usage(int status) { printf("Usage: " PACKAGE_NAME " [OPTIONS]\n\n" @@ -292,13 +267,9 @@ static int do_init(void) { static int do_loop(void) { cdtime_t interval = cf_get_default_interval(); - cdtime_t wait_until; - - wait_until = cdtime() + interval; + cdtime_t wait_until = cdtime() + interval; while (loop == 0) { - cdtime_t now; - #if HAVE_LIBKSTAT update_kstat(); #endif @@ -306,7 +277,7 @@ static int do_loop(void) { /* Issue all plugins */ plugin_read_all(); - now = cdtime(); + cdtime_t now = cdtime(); if (now >= wait_until) { WARNING("Not sleeping because the next interval is " "%.3f seconds in the past!", @@ -333,131 +304,15 @@ static int do_shutdown(void) { return plugin_shutdown_all(); } /* int do_shutdown */ -#if COLLECT_DAEMON -static int pidfile_create(void) { - FILE *fh; - const char *file = global_option_get("PIDFile"); - - if ((fh = fopen(file, "w")) == NULL) { - ERROR("fopen (%s): %s", file, STRERRNO); - return 1; - } - - fprintf(fh, "%i\n", (int)getpid()); - fclose(fh); - - return 0; -} /* static int pidfile_create (const char *file) */ - -static int pidfile_remove(void) { - const char *file = global_option_get("PIDFile"); - if (file == NULL) - return 0; - - return unlink(file); -} /* static int pidfile_remove (const char *file) */ -#endif /* COLLECT_DAEMON */ - -#ifdef KERNEL_LINUX -static int notify_upstart(void) { - 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; - } - - NOTICE("Upstart detected, stopping now to signal readiness."); - raise(SIGSTOP); - unsetenv("UPSTART_JOB"); - - return 1; -} - -static int notify_systemd(void) { - 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 ((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 readiness."); - - 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) { - ERROR("creating UNIX socket failed: %s", STRERRNO); - return 0; - } - - su.sun_family = AF_UNIX; - 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); - } - - if (sendto(fd, buffer, strlen(buffer), MSG_NOSIGNAL, (void *)&su, - (socklen_t)su_size) < 0) { - ERROR("sendto(\"%s\") failed: %s", notifysocket, STRERRNO); - close(fd); - return 0; - } - - unsetenv("NOTIFY_SOCKET"); - close(fd); - return 1; -} -#endif /* KERNEL_LINUX */ - -struct cmdline_config { - bool test_config; - bool test_readall; - bool create_basedir; - const char *configfile; - bool daemonize; -}; - static void read_cmdline(int argc, char **argv, struct cmdline_config *config) { /* read options */ while (1) { - int c; - c = getopt(argc, argv, "htTC:" + int c = getopt(argc, argv, + "BhtTC:" #if COLLECT_DAEMON - "fP:" + "fP:" #endif - ); + ); if (c == -1) break; @@ -489,7 +344,6 @@ static void read_cmdline(int argc, char **argv, struct cmdline_config *config) { #endif /* COLLECT_DAEMON */ case 'h': exit_usage(0); - break; default: exit_usage(1); } /* switch (c) */ @@ -497,7 +351,6 @@ static void read_cmdline(int argc, char **argv, struct cmdline_config *config) { } static int configure_collectd(struct cmdline_config *config) { - const char *basedir; /* * Read options from the config file, the environment and the command * line (in that order, with later options overwriting previous ones in @@ -505,8 +358,7 @@ static int configure_collectd(struct cmdline_config *config) { * Also, this will automatically load modules. */ if (cf_read(config->configfile)) { - fprintf(stderr, "Error: Reading the config file failed!\n" - "Read the logs for details.\n"); + fprintf(stderr, "Error: Parsing the config file failed!\n"); return 1; } @@ -514,6 +366,7 @@ static int configure_collectd(struct cmdline_config *config) { * Change directory. We do this _after_ reading the config and loading * modules to relative paths work as expected. */ + const char *basedir; if ((basedir = global_option_get("BaseDir")) == NULL) { fprintf(stderr, "Don't have a basedir to use. This should not happen. Ever."); @@ -535,20 +388,19 @@ static int configure_collectd(struct cmdline_config *config) { return 0; } -int main(int argc, char **argv) { -#if COLLECT_DAEMON - pid_t pid; -#endif - int exit_status = 0; +void stop_collectd(void) { loop++; } +struct cmdline_config init_config(int argc, char **argv) { struct cmdline_config config = { - .daemonize = true, .create_basedir = true, .configfile = CONFIGFILE, + .daemonize = true, + .create_basedir = true, + .configfile = CONFIGFILE, }; read_cmdline(argc, argv, &config); if (config.test_config) - return 0; + exit(EXIT_SUCCESS); if (optind < argc) exit_usage(1); @@ -558,110 +410,18 @@ int main(int argc, char **argv) { if (configure_collectd(&config) != 0) exit(EXIT_FAILURE); -#if COLLECT_DAEMON - /* - * fork off child - */ - struct sigaction sig_chld_action = {.sa_handler = SIG_IGN}; - - sigaction(SIGCHLD, &sig_chld_action, NULL); - - /* - * 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 -#endif - ) { - int status; - - if ((pid = fork()) == -1) { - /* error */ - fprintf(stderr, "fork: %s", STRERRNO); - return 1; - } else if (pid != 0) { - /* parent */ - /* printf ("Running (PID %i)\n", pid); */ - return 0; - } - - /* Detach from session */ - setsid(); - - /* Write pidfile */ - if (pidfile_create()) - exit(2); - - /* close standard descriptors */ - close(2); - close(1); - close(0); - - status = open("/dev/null", O_RDWR); - if (status != 0) { - ERROR("Error: Could not connect `STDIN' to `/dev/null' (status %d)", - status); - return 1; - } - - status = dup(0); - if (status != 1) { - ERROR("Error: Could not connect `STDOUT' to `/dev/null' (status %d)", - status); - return 1; - } - - status = dup(0); - if (status != 2) { - ERROR("Error: Could not connect `STDERR' to `/dev/null', (status %d)", - status); - return 1; - } - } /* if (config.daemonize) */ -#endif /* COLLECT_DAEMON */ - - struct sigaction sig_pipe_action = {.sa_handler = SIG_IGN}; - - sigaction(SIGPIPE, &sig_pipe_action, NULL); - - /* - * install signal handlers - */ - struct sigaction sig_int_action = {.sa_handler = sig_int_handler}; - - if (0 != sigaction(SIGINT, &sig_int_action, NULL)) { - ERROR("Error: Failed to install a signal handler for signal INT: %s", - STRERRNO); - return 1; - } - - struct sigaction sig_term_action = {.sa_handler = sig_term_handler}; - - if (0 != sigaction(SIGTERM, &sig_term_action, NULL)) { - ERROR("Error: Failed to install a signal handler for signal TERM: %s", - STRERRNO); - return 1; - } - - struct sigaction sig_usr1_action = {.sa_handler = sig_usr1_handler}; + return config; +} - if (0 != sigaction(SIGUSR1, &sig_usr1_action, NULL)) { - ERROR("Error: Failed to install a signal handler for signal USR1: %s", - STRERRNO); - return 1; - } +int run_loop(bool test_readall) { + int exit_status = 0; - /* - * run the actual loops - */ if (do_init() != 0) { ERROR("Error: one or more plugin init callbacks failed."); exit_status = 1; } - if (config.test_readall) { + if (test_readall) { if (plugin_read_all_once() != 0) { ERROR("Error: one or more plugin read callbacks failed."); exit_status = 1; @@ -679,10 +439,5 @@ int main(int argc, char **argv) { exit_status = 1; } -#if COLLECT_DAEMON - if (config.daemonize) - pidfile_remove(); -#endif /* COLLECT_DAEMON */ - return exit_status; -} /* int main */ +} /* int run_loop */