]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-stats: Handle better write() to stats process failing with EAGAIN
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 15 Apr 2016 12:01:20 +0000 (15:01 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Sun, 17 Apr 2016 17:45:01 +0000 (20:45 +0300)
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.

src/lib-stats/stats-connection.c

index 389ed861c4849235f35b0033bf49b94a2a2db4e2..740acad7df5e18306ba7a86f2eff583726003962 100644 (file)
@@ -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 <unistd.h>
 #include <fcntl.h>
 
+#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. */