From: Timo Sirainen Date: Fri, 15 Apr 2016 12:01:20 +0000 (+0300) Subject: lib-stats: Handle better write() to stats process failing with EAGAIN X-Git-Tag: 2.3.0.rc1~4018 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ba081c6b0b9b07b390533fd240712b96e4c1ce36;p=thirdparty%2Fdovecot%2Fcore.git lib-stats: Handle better write() to stats process failing with EAGAIN It only means that the stats process is too busy and the FIFO is filled up. Retrying the write later should work. We also don't want to log too much about the same warning, so do it only once per 30 seconds. --- diff --git a/src/lib-stats/stats-connection.c b/src/lib-stats/stats-connection.c index 389ed861c4..740acad7df 100644 --- a/src/lib-stats/stats-connection.c +++ b/src/lib-stats/stats-connection.c @@ -1,6 +1,7 @@ /* Copyright (c) 2011-2016 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "ioloop.h" #include "str.h" #include "master-service.h" #include "stats-connection.h" @@ -8,6 +9,8 @@ #include #include +#define STATS_EAGAIN_WARN_INTERVAL_SECS 30 + struct stats_connection { int refcount; @@ -15,6 +18,7 @@ struct stats_connection { char *path; bool open_failed; + time_t next_warning_timestamp; }; static bool stats_connection_open(struct stats_connection *conn) @@ -89,7 +93,17 @@ void stats_connection_send(struct stats_connection *conn, const string_t *str) } ret = write(conn->fd, str_data(str), str_len(str)); - if (ret != (ssize_t)str_len(str)) { + if (ret == (ssize_t)str_len(str)) { + /* success */ + } else if (ret < 0 && errno == EAGAIN) { + /* stats process is busy */ + if (ioloop_time > conn->next_warning_timestamp) { + i_warning("write(%s) failed: %m (stats process is busy)", conn->path); + conn->next_warning_timestamp = ioloop_time + + STATS_EAGAIN_WARN_INTERVAL_SECS; + } + } else { + /* error - reconnect */ if (ret < 0) { /* don't log EPIPE errors. they can happen when Dovecot is stopped. */