diff options
author | Stefan Bühler <stbuehler@web.de> | 2009-02-19 13:13:58 +0000 |
---|---|---|
committer | Stefan Bühler <stbuehler@web.de> | 2009-02-19 13:13:58 +0000 |
commit | a15e1ce4bb3f78667aebc95857121c822786aa9d (patch) | |
tree | d6892fe5c9566353c0b924924681204db21a5b49 /src/mod_rrdtool.c | |
parent | 6ea62edd5264db9493a5030fcd9174f4d1e4ae56 (diff) | |
download | lighttpd-git-a15e1ce4bb3f78667aebc95857121c822786aa9d.tar.gz |
Handle EINTR in mod_rrdtool (fixes #604)
git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@2400 152afb58-edef-0310-8abb-c4023f1b3aa9
Diffstat (limited to 'src/mod_rrdtool.c')
-rw-r--r-- | src/mod_rrdtool.c | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/src/mod_rrdtool.c b/src/mod_rrdtool.c index f405e259..67c44377 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)); @@ -194,6 +194,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; @@ -229,7 +270,7 @@ static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s) "RRA:MIN:0.5:24:775 " "RRA:MIN:0.5:288:797\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))) { log_error_write(srv, __FILE__, __LINE__, "ss", "rrdtool-write: failed", strerror(errno)); @@ -237,7 +278,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)); @@ -390,7 +431,7 @@ TRIGGER_FUNC(mod_rrd_trigger) { buffer_append_long(p->cmd, s->requests); 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", @@ -400,7 +441,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", |