dovecot-2.0: When writing to logs, ignore write()=EINTR failures...
dovecot at dovecot.org
dovecot at dovecot.org
Tue Sep 14 19:39:50 EEST 2010
details: http://hg.dovecot.org/dovecot-2.0/rev/5626fee3b7b9
changeset: 12118:5626fee3b7b9
user: Timo Sirainen <tss at iki.fi>
date: Tue Sep 14 17:39:40 2010 +0100
description:
When writing to logs, ignore write()=EINTR failures from non-terminal signals.
The previous code failed after 3 successive EINTRs, which was possible if
the process got a lot of signals (e.g. master process getting lots of SIGCHLD
signals).
diffstat:
src/lib/failures.c | 44 +++++++++++++++++++++++++++++---------------
1 files changed, 29 insertions(+), 15 deletions(-)
diffs (69 lines):
diff -r 7f364dafc675 -r 5626fee3b7b9 src/lib/failures.c
--- a/src/lib/failures.c Tue Sep 14 17:38:08 2010 +0100
+++ b/src/lib/failures.c Tue Sep 14 17:39:40 2010 +0100
@@ -5,6 +5,7 @@
#include "str.h"
#include "hostpid.h"
#include "network.h"
+#include "lib-signals.h"
#include "backtrace-string.h"
#include "printf-format-fix.h"
#include "write-full.h"
@@ -85,7 +86,8 @@
struct ioloop *ioloop;
struct io *io;
ssize_t ret;
- unsigned int eintr_count = 0;
+ unsigned int prev_signal_term_counter = signal_term_counter;
+ unsigned int terminal_eintr_count = 0;
while ((ret = write(fd, data, len)) != (ssize_t)len) {
if (ret > 0) {
@@ -99,21 +101,33 @@
errno = ENOSPC;
return -1;
}
- if (errno == EINTR && ++eintr_count < 3) {
- /* we don't want to die because of this.
- try again a couple of times. */
- continue;
+ switch (errno) {
+ case EAGAIN:
+ /* wait until we can write more. this can happen at
+ least when writing to terminal, even if fd is
+ blocking. */
+ ioloop = io_loop_create();
+ io = io_add(fd, IO_WRITE, log_fd_flush_stop, ioloop);
+ io_loop_run(ioloop);
+ io_remove(&io);
+ io_loop_destroy(&ioloop);
+ break;
+ case EINTR:
+ if (prev_signal_term_counter == signal_term_counter) {
+ /* non-terminal signal. ignore. */
+ } else if (terminal_eintr_count++ == 0) {
+ /* we'd rather not die in the middle of
+ writing to log. try again once more */
+ } else {
+ /* received two terminal signals.
+ someone wants us dead. */
+ return -1;
+ }
+ break;
+ default:
+ return -1;
}
- if (errno != EAGAIN)
- return -1;
-
- /* wait until we can write more. this can happen at least
- when writing to terminal, even if fd is blocking. */
- ioloop = io_loop_create();
- io = io_add(fd, IO_WRITE, log_fd_flush_stop, ioloop);
- io_loop_run(ioloop);
- io_remove(&io);
- io_loop_destroy(&ioloop);
+ prev_signal_term_counter = signal_term_counter;
}
return 0;
}
More information about the dovecot-cvs
mailing list