summaryrefslogtreecommitdiff
path: root/src/mod_rrdtool.c
diff options
context:
space:
mode:
authorStefan Bühler <stbuehler@web.de>2009-02-19 13:13:58 +0000
committerStefan Bühler <stbuehler@web.de>2009-02-19 13:13:58 +0000
commita15e1ce4bb3f78667aebc95857121c822786aa9d (patch)
treed6892fe5c9566353c0b924924681204db21a5b49 /src/mod_rrdtool.c
parent6ea62edd5264db9493a5030fcd9174f4d1e4ae56 (diff)
downloadlighttpd-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.c51
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",