The default action for the PIPE signal is to terminate the process. This
is not really what we want for collectd, as e.g. a client of the unixsock
plugin (which might even be running without root privileges) could kill
the daemon by closing the socket right after sending a request.
The signal now gets ignored and each I/O function is checked for success.
To simply that, the unixsock's output stream is now configured to be line
buffered, removing the need to call fflush() (which could fail as well and
would have to be checked for success).
While I was at it, I renamed the sigaction struct for SIGCHLD to fit the
coding style used elsewhere in collectd.
Signed-off-by: Sebastian Harl <sh@tokkee.org>
Signed-off-by: Florian Forster <octo@huhu.verplant.org>
struct sigaction sig_int_action;
struct sigaction sig_term_action;
struct sigaction sig_usr1_action;
struct sigaction sig_int_action;
struct sigaction sig_term_action;
struct sigaction sig_usr1_action;
+ struct sigaction sig_pipe_action;
char *configfile = CONFIGFILE;
int test_config = 0;
const char *basedir;
#if COLLECT_DAEMON
char *configfile = CONFIGFILE;
int test_config = 0;
const char *basedir;
#if COLLECT_DAEMON
- struct sigaction sigChldAction;
+ struct sigaction sig_chld_action;
pid_t pid;
int daemonize = 1;
#endif
pid_t pid;
int daemonize = 1;
#endif
- memset (&sigChldAction, '\0', sizeof (sigChldAction));
- sigChldAction.sa_handler = SIG_IGN;
- sigaction (SIGCHLD, &sigChldAction, NULL);
+ memset (&sig_chld_action, '\0', sizeof (sig_chld_action));
+ sig_chld_action.sa_handler = SIG_IGN;
+ sigaction (SIGCHLD, &sig_chld_action, NULL);
} /* if (daemonize) */
#endif /* COLLECT_DAEMON */
} /* if (daemonize) */
#endif /* COLLECT_DAEMON */
+ memset (&sig_pipe_action, '\0', sizeof (sig_pipe_action));
+ sig_pipe_action.sa_handler = SIG_IGN;
+ sigaction (SIGPIPE, &sig_pipe_action, NULL);
+
/*
* install signal handlers
*/
/*
* install signal handlers
*/
pthread_exit ((void *) 1);
}
pthread_exit ((void *) 1);
}
- while (fgets (buffer, sizeof (buffer), fhin) != NULL)
+ /* change output buffer to line buffered mode */
+ if (setvbuf (fhout, NULL, _IOLBF, 0) != 0)
+ {
+ char errbuf[1024];
+ ERROR ("unixsock plugin: setvbuf failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ fclose (fhin);
+ fclose (fhout);
+ pthread_exit ((void *) 1);
+ }
+
+ while (42)
+ errno = 0;
+ if (fgets (buffer, sizeof (buffer), fhin) == NULL)
+ {
+ if (errno != 0)
+ {
+ char errbuf[1024];
+ WARNING ("unixsock plugin: failed to read from socket #%i: %s",
+ fileno (fhin),
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ }
+ break;
+ }
+
len = strlen (buffer);
while ((len > 0)
&& ((buffer[len - 1] == '\n') || (buffer[len - 1] == '\r')))
len = strlen (buffer);
while ((len > 0)
&& ((buffer[len - 1] == '\n') || (buffer[len - 1] == '\r')))
- fprintf (fhout, "-1 Unknown command: %s\n", fields[0]);
- fflush (fhout);
+ if (fprintf (fhout, "-1 Unknown command: %s\n", fields[0]) < 0)
+ {
+ char errbuf[1024];
+ WARNING ("unixsock plugin: failed to write to socket #%i: %s",
+ fileno (fhout),
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ break;
+ }
#include "common.h"
#include "plugin.h"
#include "common.h"
#include "plugin.h"
+#define print_to_socket(fh, ...) \
+ if (fprintf (fh, __VA_ARGS__) < 0) { \
+ char errbuf[1024]; \
+ WARNING ("handle_flush: failed to write to socket #%i: %s", \
+ fileno (fh), sstrerror (errno, errbuf, sizeof (errbuf))); \
+ return -1; \
+ }
+
int handle_flush (FILE *fh, char **fields, int fields_num)
{
int success = 0;
int handle_flush (FILE *fh, char **fields, int fields_num)
{
int success = 0;
- fprintf (fh, "-1 Cannot parse option %s\n", option);
- fflush (fh);
+ print_to_socket (fh, "-1 Cannot parse option %s\n", option);
return (-1);
}
}
if ((success + error) > 0)
{
return (-1);
}
}
if ((success + error) > 0)
{
- fprintf (fh, "0 Done: %i successful, %i errors\n", success, error);
+ print_to_socket (fh, "0 Done: %i successful, %i errors\n",
+ success, error);
}
else
{
plugin_flush_all (timeout);
}
else
{
plugin_flush_all (timeout);
- fprintf (fh, "0 Done\n");
+ print_to_socket (fh, "0 Done\n");
return (0);
} /* int handle_flush */
return (0);
} /* int handle_flush */
+#define print_to_socket(fh, ...) \
+ if (fprintf (fh, __VA_ARGS__) < 0) { \
+ char errbuf[1024]; \
+ WARNING ("handle_getval: failed to write to socket #%i: %s", \
+ fileno (fh), sstrerror (errno, errbuf, sizeof (errbuf))); \
+ return -1; \
+ }
+
int handle_getval (FILE *fh, char **fields, int fields_num)
{
char *hostname;
int handle_getval (FILE *fh, char **fields, int fields_num)
{
char *hostname;
if (fields_num != 2)
{
DEBUG ("unixsock plugin: Wrong number of fields: %i", fields_num);
if (fields_num != 2)
{
DEBUG ("unixsock plugin: Wrong number of fields: %i", fields_num);
- fprintf (fh, "-1 Wrong number of fields: Got %i, expected 2.\n",
+ print_to_socket (fh, "-1 Wrong number of fields: Got %i, expected 2.\n",
return (-1);
}
DEBUG ("unixsock plugin: Got query for `%s'", fields[1]);
if (strlen (fields[1]) < strlen ("h/p/t"))
{
return (-1);
}
DEBUG ("unixsock plugin: Got query for `%s'", fields[1]);
if (strlen (fields[1]) < strlen ("h/p/t"))
{
- fprintf (fh, "-1 Invalied identifier, %s\n", fields[1]);
- fflush (fh);
+ print_to_socket (fh, "-1 Invalied identifier, %s\n", fields[1]);
if (status != 0)
{
DEBUG ("unixsock plugin: Cannot parse `%s'", fields[1]);
if (status != 0)
{
DEBUG ("unixsock plugin: Cannot parse `%s'", fields[1]);
- fprintf (fh, "-1 Cannot parse identifier.\n");
- fflush (fh);
+ print_to_socket (fh, "-1 Cannot parse identifier.\n");
sfree (identifier_copy);
return (-1);
}
sfree (identifier_copy);
return (-1);
}
if (ds == NULL)
{
DEBUG ("unixsock plugin: plugin_get_ds (%s) == NULL;", type);
if (ds == NULL)
{
DEBUG ("unixsock plugin: plugin_get_ds (%s) == NULL;", type);
- fprintf (fh, "-1 Type `%s' is unknown.\n", type);
- fflush (fh);
+ print_to_socket (fh, "-1 Type `%s' is unknown.\n", type);
sfree (identifier_copy);
return (-1);
}
sfree (identifier_copy);
return (-1);
}
status = uc_get_rate_by_name (fields[1], &values, &values_num);
if (status != 0)
{
status = uc_get_rate_by_name (fields[1], &values, &values_num);
if (status != 0)
{
- fprintf (fh, "-1 No such value\n");
- fflush (fh);
+ print_to_socket (fh, "-1 No such value\n");
sfree (identifier_copy);
return (-1);
}
sfree (identifier_copy);
return (-1);
}
ERROR ("ds[%s]->ds_num = %i, "
"but uc_get_rate_by_name returned %i values.",
ds->type, ds->ds_num, values_num);
ERROR ("ds[%s]->ds_num = %i, "
"but uc_get_rate_by_name returned %i values.",
ds->type, ds->ds_num, values_num);
- fprintf (fh, "-1 Error reading value from cache.\n");
- fflush (fh);
+ print_to_socket (fh, "-1 Error reading value from cache.\n");
sfree (values);
sfree (identifier_copy);
return (-1);
}
sfree (values);
sfree (identifier_copy);
return (-1);
}
- fprintf (fh, "%u Value%s found\n", (unsigned int) values_num,
+ print_to_socket (fh, "%u Value%s found\n", (unsigned int) values_num,
(values_num == 1) ? "" : "s");
for (i = 0; i < values_num; i++)
{
(values_num == 1) ? "" : "s");
for (i = 0; i < values_num; i++)
{
- fprintf (fh, "%s=", ds->ds[i].name);
+ print_to_socket (fh, "%s=", ds->ds[i].name);
+ {
+ print_to_socket (fh, "NaN\n");
+ }
- fprintf (fh, "%12e\n", values[i]);
+ {
+ print_to_socket (fh, "%12e\n", values[i]);
+ }
sfree (values);
sfree (identifier_copy);
sfree (values);
sfree (identifier_copy);
#include "utils_cmd_listval.h"
#include "utils_cache.h"
#include "utils_cmd_listval.h"
#include "utils_cache.h"
+#define print_to_socket(fh, ...) \
+ if (fprintf (fh, __VA_ARGS__) < 0) { \
+ char errbuf[1024]; \
+ WARNING ("handle_listval: failed to write to socket #%i: %s", \
+ fileno (fh), sstrerror (errno, errbuf, sizeof (errbuf))); \
+ return -1; \
+ }
+
int handle_listval (FILE *fh, char **fields, int fields_num)
{
char **names = NULL;
int handle_listval (FILE *fh, char **fields, int fields_num)
{
char **names = NULL;
{
DEBUG ("command listval: us_handle_listval: Wrong number of fields: %i",
fields_num);
{
DEBUG ("command listval: us_handle_listval: Wrong number of fields: %i",
fields_num);
- fprintf (fh, "-1 Wrong number of fields: Got %i, expected 1.\n",
+ print_to_socket (fh, "-1 Wrong number of fields: Got %i, expected 1.\n",
if (status != 0)
{
DEBUG ("command listval: uc_get_names failed with status %i", status);
if (status != 0)
{
DEBUG ("command listval: uc_get_names failed with status %i", status);
- fprintf (fh, "-1 uc_get_names failed.\n");
- fflush (fh);
+ print_to_socket (fh, "-1 uc_get_names failed.\n");
- fprintf (fh, "%i Value%s found\n", (int) number, (number == 1) ? "" : "s");
+ print_to_socket (fh, "%i Value%s found\n",
+ (int) number, (number == 1) ? "" : "s");
for (i = 0; i < number; i++)
for (i = 0; i < number; i++)
- fprintf (fh, "%u %s\n", (unsigned int) times[i], names[i]);
- fflush (fh);
+ print_to_socket (fh, "%u %s\n", (unsigned int) times[i], names[i]);
return (0);
} /* int handle_listval */
return (0);
} /* int handle_listval */
#include "common.h"
#include "plugin.h"
#include "common.h"
#include "plugin.h"
+#define print_to_socket(fh, ...) \
+ if (fprintf (fh, __VA_ARGS__) < 0) { \
+ char errbuf[1024]; \
+ WARNING ("handle_putnotif: failed to write to socket #%i: %s", \
+ fileno (fh), sstrerror (errno, errbuf, sizeof (errbuf))); \
+ return -1; \
+ }
+
static int parse_option_severity (notification_t *n, char *value)
{
if (strcasecmp (value, "Failure") == 0)
static int parse_option_severity (notification_t *n, char *value)
{
if (strcasecmp (value, "Failure") == 0)
if (fields_num < 4)
{
DEBUG ("cmd putnotif: Wrong number of fields: %i", fields_num);
if (fields_num < 4)
{
DEBUG ("cmd putnotif: Wrong number of fields: %i", fields_num);
- fprintf (fh, "-1 Wrong number of fields: Got %i, expected at least 4.\n",
+ print_to_socket (fh, "-1 Wrong number of fields: Got %i, "
+ "expected at least 4.\n",
status = parse_message (&n, fields + i, fields_num - i);
if (status != 0)
{
status = parse_message (&n, fields + i, fields_num - i);
if (status != 0)
{
- fprintf (fh, "-1 Error parsing the message. Have you hit the "
+ print_to_socket (fh, "-1 Error parsing the message. Have you hit the "
"limit of %u bytes?\n", (unsigned int) sizeof (n.message));
}
break;
"limit of %u bytes?\n", (unsigned int) sizeof (n.message));
}
break;
status = parse_option (&n, fields[i]);
if (status != 0)
{
status = parse_option (&n, fields[i]);
if (status != 0)
{
- fprintf (fh, "-1 Error parsing option `%s'\n", fields[i]);
+ print_to_socket (fh, "-1 Error parsing option `%s'\n", fields[i]);
/* Check for required fields and complain if anything is missing. */
if ((status == 0) && (n.severity == 0))
{
/* Check for required fields and complain if anything is missing. */
if ((status == 0) && (n.severity == 0))
{
- fprintf (fh, "-1 Option `severity' missing.\n");
+ print_to_socket (fh, "-1 Option `severity' missing.\n");
status = -1;
}
if ((status == 0) && (n.time == 0))
{
status = -1;
}
if ((status == 0) && (n.time == 0))
{
- fprintf (fh, "-1 Option `time' missing.\n");
+ print_to_socket (fh, "-1 Option `time' missing.\n");
status = -1;
}
if ((status == 0) && (strlen (n.message) == 0))
{
status = -1;
}
if ((status == 0) && (strlen (n.message) == 0))
{
- fprintf (fh, "-1 No message or message of length 0 given.\n");
+ print_to_socket (fh, "-1 No message or message of length 0 given.\n");
if (status == 0)
{
plugin_dispatch_notification (&n);
if (status == 0)
{
plugin_dispatch_notification (&n);
- fprintf (fh, "0 Success\n");
+ print_to_socket (fh, "0 Success\n");
return (0);
} /* int handle_putnotif */
return (0);
} /* int handle_putnotif */
#include "common.h"
#include "plugin.h"
#include "common.h"
#include "plugin.h"
+#define print_to_socket(fh, ...) \
+ if (fprintf (fh, __VA_ARGS__) < 0) { \
+ char errbuf[1024]; \
+ WARNING ("handle_putval: failed to write to socket #%i: %s", \
+ fileno (fh), sstrerror (errno, errbuf, sizeof (errbuf))); \
+ return -1; \
+ }
+
static int parse_value (const data_set_t *ds, value_list_t *vl,
const char *type,
FILE *fh, char *buffer)
static int parse_value (const data_set_t *ds, value_list_t *vl,
const char *type,
FILE *fh, char *buffer)
char *value_str = strchr (time_str, ':');
if (value_str == NULL)
{
char *value_str = strchr (time_str, ':');
if (value_str == NULL)
{
- fprintf (fh, "-1 No time found.\n");
+ print_to_socket (fh, "-1 No time found.\n");
return (-1);
}
*value_str = '\0'; value_str++;
return (-1);
}
*value_str = '\0'; value_str++;
"Number of values incorrect: "
"Got %i, expected %i. Identifier is `%s'.",
i, vl->values_len, identifier);
"Number of values incorrect: "
"Got %i, expected %i. Identifier is `%s'.",
i, vl->values_len, identifier);
- fprintf (fh, "-1 Number of values incorrect: "
+ print_to_socket (fh, "-1 Number of values incorrect: "
"Got %i, expected %i.\n",
i, vl->values_len);
return (-1);
"Got %i, expected %i.\n",
i, vl->values_len);
return (-1);
{
DEBUG ("cmd putval: Wrong number of fields: %i",
fields_num);
{
DEBUG ("cmd putval: Wrong number of fields: %i",
fields_num);
- fprintf (fh, "-1 Wrong number of fields: Got %i, "
+ print_to_socket (fh, "-1 Wrong number of fields: Got %i, "
"expected at least 3.\n",
fields_num);
"expected at least 3.\n",
fields_num);
if (status != 0)
{
DEBUG ("cmd putval: Cannot parse `%s'", fields[1]);
if (status != 0)
{
DEBUG ("cmd putval: Cannot parse `%s'", fields[1]);
- fprintf (fh, "-1 Cannot parse identifier.\n");
- fflush (fh);
+ print_to_socket (fh, "-1 Cannot parse identifier.\n");
sfree (identifier_copy);
return (-1);
}
sfree (identifier_copy);
return (-1);
}
|| ((type_instance != NULL)
&& (strlen (type_instance) >= sizeof (vl.type_instance))))
{
|| ((type_instance != NULL)
&& (strlen (type_instance) >= sizeof (vl.type_instance))))
{
- fprintf (fh, "-1 Identifier too long.\n");
- fflush (fh);
+ print_to_socket (fh, "-1 Identifier too long.\n");
sfree (identifier_copy);
return (-1);
}
sfree (identifier_copy);
return (-1);
}
vl.values = (value_t *) malloc (vl.values_len * sizeof (value_t));
if (vl.values == NULL)
{
vl.values = (value_t *) malloc (vl.values_len * sizeof (value_t));
if (vl.values == NULL)
{
- fprintf (fh, "-1 malloc failed.\n");
- fflush (fh);
+ print_to_socket (fh, "-1 malloc failed.\n");
sfree (identifier_copy);
return (-1);
}
sfree (identifier_copy);
return (-1);
}
{
if (parse_option (&vl, fields[i]) != 0)
{
{
if (parse_option (&vl, fields[i]) != 0)
{
- fprintf (fh, "-1 Error parsing option `%s'\n",
+ print_to_socket (fh, "-1 Error parsing option `%s'\n",
/* Done parsing the options. */
if (i == fields_num)
/* Done parsing the options. */
if (i == fields_num)
- fprintf (fh, "0 Success\n");
- fflush (fh);
+ print_to_socket (fh, "0 Success\n");
sfree (vl.values);
sfree (identifier_copy);
sfree (vl.values);
sfree (identifier_copy);