Mercurial > dovecot > core-2.2
changeset 12118:5626fee3b7b9
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).
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 14 Sep 2010 17:39:40 +0100 |
parents | 7f364dafc675 |
children | fac83abe8aaf |
files | src/lib/failures.c |
diffstat | 1 files changed, 29 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- 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; - } - if (errno != EAGAIN) + 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; - - /* 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; }