summaryrefslogtreecommitdiff
path: root/src/mod_rrdtool.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mod_rrdtool.c')
-rw-r--r--src/mod_rrdtool.c123
1 files changed, 84 insertions, 39 deletions
diff --git a/src/mod_rrdtool.c b/src/mod_rrdtool.c
index 28003c4..2cb4640 100644
--- a/src/mod_rrdtool.c
+++ b/src/mod_rrdtool.c
@@ -92,11 +92,11 @@ FREE_FUNC(mod_rrd_free) {
}
int mod_rrd_create_pipe(server *srv, plugin_data *p) {
+#ifdef HAVE_FORK
pid_t pid;
int to_rrdtool_fds[2];
int from_rrdtool_fds[2];
-#ifdef HAVE_FORK
if (pipe(to_rrdtool_fds)) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"pipe failed: ", strerror(errno));
@@ -132,13 +132,6 @@ int mod_rrd_create_pipe(server *srv, plugin_data *p) {
/* not needed */
close(to_rrdtool_fds[1]);
- close(STDERR_FILENO);
-
- if (srv->errorlog_mode == ERRORLOG_FILE) {
- dup2(srv->errorlog_fd, STDERR_FILENO);
- close(srv->errorlog_fd);
- }
-
/* set up args */
argc = 3;
args = malloc(sizeof(*args) * argc);
@@ -148,6 +141,8 @@ int mod_rrd_create_pipe(server *srv, plugin_data *p) {
args[i++] = dash;
args[i++] = NULL;
+ openDevNull(STDERR_FILENO);
+
/* we don't need the client socket */
for (i = 3; i < 256; i++) {
close(i);
@@ -156,7 +151,7 @@ int mod_rrd_create_pipe(server *srv, plugin_data *p) {
/* exec the cgi */
execv(args[0], args);
- log_error_write(srv, __FILE__, __LINE__, "sss", "spawing rrdtool failed: ", strerror(errno), args[0]);
+ /* log_error_write(srv, __FILE__, __LINE__, "sss", "spawing rrdtool failed: ", strerror(errno), args[0]); */
/* */
SEGFAULT();
@@ -177,6 +172,11 @@ int mod_rrd_create_pipe(server *srv, plugin_data *p) {
p->read_fd = from_rrdtool_fds[0];
p->rrdtool_pid = pid;
+#ifdef FD_CLOEXEC
+ fcntl(p->write_fd, F_SETFD, FD_CLOEXEC);
+ fcntl(p->read_fd, F_SETFD, FD_CLOEXEC);
+#endif
+
break;
}
}
@@ -187,6 +187,47 @@ int mod_rrd_create_pipe(server *srv, plugin_data *p) {
#endif
}
+/* read/write wrappers to catch EINTR */
+
+/* write to blocking socket; blocks until all data is sent, write returns 0 or an error (apart from EINTR) occurs. */
+static ssize_t safe_write(int fd, const void *buf, size_t count) {
+ ssize_t res, sum = 0;
+
+ for (;;) {
+ res = write(fd, buf, count);
+ if (res >= 0) {
+ sum += res;
+ /* do not try again if res == 0 */
+ if (res == 0 || (size_t) res == count) return sum;
+ count -= res;
+ buf = (const char*) buf + res;
+ continue;
+ }
+ switch (errno) {
+ case EINTR:
+ continue;
+ default:
+ return -1;
+ }
+ }
+}
+
+/* this assumes we get enough data on a successful read */
+static ssize_t safe_read(int fd, void *buf, size_t count) {
+ ssize_t res;
+
+ for (;;) {
+ res = read(fd, buf, count);
+ if (res >= 0) return res;
+ switch (errno) {
+ case EINTR:
+ continue;
+ default:
+ return -1;
+ }
+ }
+}
+
static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s) {
struct stat st;
@@ -202,26 +243,27 @@ static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s)
int r ;
/* create a new one */
- BUFFER_COPY_STRING_CONST(p->cmd, "create ");
+ buffer_copy_string_len(p->cmd, CONST_STR_LEN("create "));
buffer_append_string_buffer(p->cmd, s->path_rrd);
- buffer_append_string(p->cmd, " --step 60 ");
- buffer_append_string(p->cmd, "DS:InOctets:ABSOLUTE:600:U:U ");
- buffer_append_string(p->cmd, "DS:OutOctets:ABSOLUTE:600:U:U ");
- buffer_append_string(p->cmd, "DS:Requests:ABSOLUTE:600:U:U ");
- buffer_append_string(p->cmd, "RRA:AVERAGE:0.5:1:600 ");
- buffer_append_string(p->cmd, "RRA:AVERAGE:0.5:6:700 ");
- buffer_append_string(p->cmd, "RRA:AVERAGE:0.5:24:775 ");
- buffer_append_string(p->cmd, "RRA:AVERAGE:0.5:288:797 ");
- buffer_append_string(p->cmd, "RRA:MAX:0.5:1:600 ");
- buffer_append_string(p->cmd, "RRA:MAX:0.5:6:700 ");
- buffer_append_string(p->cmd, "RRA:MAX:0.5:24:775 ");
- buffer_append_string(p->cmd, "RRA:MAX:0.5:288:797 ");
- buffer_append_string(p->cmd, "RRA:MIN:0.5:1:600 ");
- buffer_append_string(p->cmd, "RRA:MIN:0.5:6:700 ");
- buffer_append_string(p->cmd, "RRA:MIN:0.5:24:775 ");
- buffer_append_string(p->cmd, "RRA:MIN:0.5:288:797\n");
-
- if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
+ buffer_append_string_len(p->cmd, CONST_STR_LEN(
+ " --step 60 "
+ "DS:InOctets:ABSOLUTE:600:U:U "
+ "DS:OutOctets:ABSOLUTE:600:U:U "
+ "DS:Requests:ABSOLUTE:600:U:U "
+ "RRA:AVERAGE:0.5:1:600 "
+ "RRA:AVERAGE:0.5:6:700 "
+ "RRA:AVERAGE:0.5:24:775 "
+ "RRA:AVERAGE:0.5:288:797 "
+ "RRA:MAX:0.5:1:600 "
+ "RRA:MAX:0.5:6:700 "
+ "RRA:MAX:0.5:24:775 "
+ "RRA:MAX:0.5:288:797 "
+ "RRA:MIN:0.5:1:600 "
+ "RRA:MIN:0.5:6:700 "
+ "RRA:MIN:0.5:24:775 "
+ "RRA:MIN:0.5:288:797\n"));
+
+ if (-1 == (r = safe_write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"rrdtool-write: failed", strerror(errno));
@@ -229,7 +271,7 @@ static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s)
}
buffer_prepare_copy(p->resp, 4096);
- if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
+ if (-1 == (r = safe_read(p->read_fd, p->resp->ptr, p->resp->size))) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"rrdtool-read: failed", strerror(errno));
@@ -372,17 +414,17 @@ TRIGGER_FUNC(mod_rrd_trigger) {
if (HANDLER_GO_ON != mod_rrdtool_create_rrd(srv, p, s)) return HANDLER_ERROR;
- BUFFER_COPY_STRING_CONST(p->cmd, "update ");
+ buffer_copy_string_len(p->cmd, CONST_STR_LEN("update "));
buffer_append_string_buffer(p->cmd, s->path_rrd);
- BUFFER_APPEND_STRING_CONST(p->cmd, " N:");
+ buffer_append_string_len(p->cmd, CONST_STR_LEN(" N:"));
buffer_append_off_t(p->cmd, s->bytes_read);
- BUFFER_APPEND_STRING_CONST(p->cmd, ":");
+ buffer_append_string_len(p->cmd, CONST_STR_LEN(":"));
buffer_append_off_t(p->cmd, s->bytes_written);
- BUFFER_APPEND_STRING_CONST(p->cmd, ":");
+ buffer_append_string_len(p->cmd, CONST_STR_LEN(":"));
buffer_append_long(p->cmd, s->requests);
- BUFFER_APPEND_STRING_CONST(p->cmd, "\n");
+ buffer_append_string_len(p->cmd, CONST_STR_LEN("\n"));
- if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
+ if (-1 == (r = safe_write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
p->rrdtool_running = 0;
log_error_write(srv, __FILE__, __LINE__, "ss",
@@ -392,7 +434,7 @@ TRIGGER_FUNC(mod_rrd_trigger) {
}
buffer_prepare_copy(p->resp, 4096);
- if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
+ if (-1 == (r = safe_read(p->read_fd, p->resp->ptr, p->resp->size))) {
p->rrdtool_running = 0;
log_error_write(srv, __FILE__, __LINE__, "ss",
@@ -405,12 +447,15 @@ TRIGGER_FUNC(mod_rrd_trigger) {
if (p->resp->ptr[0] != 'O' ||
p->resp->ptr[1] != 'K') {
- p->rrdtool_running = 0;
+ /* don't fail on this error if we just started (graceful restart, the old one might have just updated too) */
+ if (!(strstr(p->resp->ptr, "(minimum one second step)") && (srv->cur_ts - srv->startup_ts < 3))) {
+ p->rrdtool_running = 0;
- log_error_write(srv, __FILE__, __LINE__, "sbb",
+ log_error_write(srv, __FILE__, __LINE__, "sbb",
"rrdtool-response:", p->cmd, p->resp);
- return HANDLER_ERROR;
+ return HANDLER_ERROR;
+ }
}
s->requests = 0;
s->bytes_written = 0;