X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fexec.c;h=639b5d45b9dd310509dd0a763404de6e6ffabb7b;hb=48cde211ba0b69555478b2069ca0bc4051661b0b;hp=a78f902fdef5634b11baaae07045a8ea85578ee5;hpb=ec404735b0676bb44fdba10f3760e1ba9632405a;p=collectd.git diff --git a/src/exec.c b/src/exec.c index a78f902f..639b5d45 100644 --- a/src/exec.c +++ b/src/exec.c @@ -1,6 +1,8 @@ /** * collectd - src/exec.c - * Copyright (C) 2007,2008 Florian octo Forster + * Copyright (C) 2007-2010 Florian octo Forster + * Copyright (C) 2007-2009 Sebastian Harl + * Copyright (C) 2008 Peter Holik * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -17,8 +19,12 @@ * * Authors: * Florian octo Forster + * Sebastian Harl + * Peter Holik **/ +#define _BSD_SOURCE /* For setgroups */ + #include "collectd.h" #include "common.h" #include "plugin.h" @@ -78,7 +84,7 @@ static pthread_mutex_t pl_lock = PTHREAD_MUTEX_INITIALIZER; /* * Functions */ -static void sigchld_handler (int signal) /* {{{ */ +static void sigchld_handler (int __attribute__((unused)) signal) /* {{{ */ { pid_t pid; int status; @@ -259,6 +265,26 @@ static int exec_config (oconfig_item_t *ci) /* {{{ */ return (0); } /* int exec_config }}} */ +static void set_environment (void) /* {{{ */ +{ + char buffer[1024]; + +#ifdef HAVE_SETENV + ssnprintf (buffer, sizeof (buffer), "%i", interval_g); + setenv ("COLLECTD_INTERVAL", buffer, /* overwrite = */ 1); + + ssnprintf (buffer, sizeof (buffer), "%s", hostname_g); + setenv ("COLLECTD_HOSTNAME", buffer, /* overwrite = */ 1); +#else + ssnprintf (buffer, sizeof (buffer), "COLLECTD_INTERVAL=%i", interval_g); + putenv (buffer); + + ssnprintf (buffer, sizeof (buffer), "COLLECTD_HOSTNAME=%s", hostname_g); + putenv (buffer); +#endif +} /* }}} void set_environment */ + +__attribute__((noreturn)) static void exec_child (program_list_t *pl) /* {{{ */ { int status; @@ -275,8 +301,8 @@ static void exec_child (program_list_t *pl) /* {{{ */ status = getpwnam_r (pl->user, &sp, nambuf, sizeof (nambuf), &sp_ptr); if (status != 0) { - ERROR ("exec plugin: getpwnam_r failed: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); + ERROR ("exec plugin: Failed to get user information for user ``%s'': %s", + pl->user, sstrerror (errno, errbuf, sizeof (errbuf))); exit (-1); } if (sp_ptr == NULL) @@ -305,7 +331,8 @@ static void exec_child (program_list_t *pl) /* {{{ */ status = getgrnam_r (pl->group, &gr, nambuf, sizeof (nambuf), &gr_ptr); if (0 != status) { - ERROR ("exec plugin: getgrnam_r failed: %s", + ERROR ("exec plugin: Failed to get group information " + "for group ``%s'': %s", pl->group, sstrerror (errno, errbuf, sizeof (errbuf))); exit (-1); } @@ -371,11 +398,20 @@ static void exec_child (program_list_t *pl) /* {{{ */ status = execvp (pl->exec, pl->argv); - ERROR ("exec plugin: exec failed: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); + ERROR ("exec plugin: Failed to execute ``%s'': %s", + pl->exec, sstrerror (errno, errbuf, sizeof (errbuf))); exit (-1); } /* void exec_child }}} */ +static void reset_signal_mask (void) /* {{{ */ +{ + sigset_t ss; + + memset (&ss, 0, sizeof (ss)); + sigemptyset (&ss); + sigprocmask (SIG_SETMASK, &ss, /* old mask = */ NULL); +} /* }}} void reset_signal_mask */ + /* * Creates three pipes (one for reading, one for writing and one for errors), * forks a child, sets up the pipes so that fd_in is connected to STDIN of @@ -462,6 +498,11 @@ static int fork_child (program_list_t *pl, int *fd_in, int *fd_out, int *fd_err) close (fd_pipe_err[1]); } + set_environment (); + + /* Unblock all signals */ + reset_signal_mask (); + exec_child (pl); /* does not return */ } @@ -518,7 +559,13 @@ static void *exec_read_one (void *arg) /* {{{ */ status = fork_child (pl, NULL, &fd, &fd_err); if (status < 0) + { + /* Reset the "running" flag */ + pthread_mutex_lock (&pl_lock); + pl->flags &= ~PL_RUNNING; + pthread_mutex_unlock (&pl_lock); pthread_exit ((void *) 1); + } pl->pid = status; assert (pl->pid != 0); @@ -585,7 +632,17 @@ static void *exec_read_one (void *arg) /* {{{ */ if (errno == EAGAIN || errno == EINTR) continue; break; } - else if (len == 0) break; /* We've reached EOF */ + else if (len == 0) + { + /* We've reached EOF */ + NOTICE ("exec plugin: Program `%s' has closed STDERR.", + pl->exec); + close (fd_err); + FD_CLR (fd_err, &fdset); + highest_fd = fd; + fd_err = -1; + continue; + } pbuffer_err[len] = '\0'; @@ -615,6 +672,7 @@ static void *exec_read_one (void *arg) /* {{{ */ copy = fdset; } + DEBUG ("exec plugin: exec_read_one: Waiting for `%s' to exit.", pl->exec); if (waitpid (pl->pid, &status, 0) > 0) pl->status = status; @@ -628,7 +686,8 @@ static void *exec_read_one (void *arg) /* {{{ */ pthread_mutex_unlock (&pl_lock); close (fd); - close (fd_err); + if (fd_err >= 0) + close (fd_err); pthread_exit ((void *) 0); return (NULL); @@ -712,7 +771,9 @@ static void *exec_notification_one (void *arg) /* {{{ */ DEBUG ("exec plugin: Child %i exited with status %i.", pid, status); - plugin_notification_meta_free (n); + if (n->meta != NULL) + plugin_notification_meta_free (n->meta); + n->meta = NULL; sfree (arg); pthread_exit ((void *) 0); return (NULL); @@ -760,7 +821,8 @@ static int exec_read (void) /* {{{ */ return (0); } /* int exec_read }}} */ -static int exec_notification (const notification_t *n) +static int exec_notification (const notification_t *n, /* {{{ */ + user_data_t __attribute__((unused)) *user_data) { program_list_t *pl; program_list_and_notification_t *pln; @@ -800,7 +862,7 @@ static int exec_notification (const notification_t *n) } /* for (pl) */ return (0); -} /* int exec_notification */ +} /* }}} int exec_notification */ static int exec_shutdown (void) /* {{{ */ { @@ -833,7 +895,8 @@ void module_register (void) plugin_register_complex_config ("exec", exec_config); plugin_register_init ("exec", exec_init); plugin_register_read ("exec", exec_read); - plugin_register_notification ("exec", exec_notification); + plugin_register_notification ("exec", exec_notification, + /* user_data = */ NULL); plugin_register_shutdown ("exec", exec_shutdown); } /* void module_register */