Mercurial > dovecot > original-hg > dovecot-1.2
changeset 7229:586abf9b561c HEAD
If Dovecot master dies with a fatal failure, log the error message to a file
in base_dir. If the file exists at startup, show its contents and a comment
about looking at error logs why it happened. Hopefully this will reduce "why
Dovecot died without a reason?" questions.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 11 Feb 2008 20:47:45 +0200 |
parents | 45a083e03fba |
children | 777131d76168 |
files | src/master/main.c |
diffstat | 1 files changed, 55 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/master/main.c Mon Feb 11 20:44:23 2008 +0200 +++ b/src/master/main.c Mon Feb 11 20:47:45 2008 +0200 @@ -32,6 +32,8 @@ higher, it's not dropped. */ #define DOVECOT_MASTER_FD_MIN_LIMIT 65536 +#define FATAL_FILENAME "master-fatal.lastlog" + static const char *configfile = SYSCONFDIR "/" PACKAGE ".conf"; struct ioloop *ioloop; @@ -44,6 +46,57 @@ bool gdb; #endif +static void ATTR_NORETURN ATTR_FORMAT(3, 0) +master_fatal_callback(enum log_type type, int status, + const char *format, va_list args) +{ + const struct settings *set = settings_root->defaults; + const char *path, *str; + int fd; + + /* write the error message to a file */ + path = t_strconcat(set->base_dir, "/"FATAL_FILENAME, NULL); + fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600); + if (fd != -1) { + str = t_strdup_vprintf(format, args); + write_full(fd, str, strlen(str)); + (void)close(fd); + } + + /* write it to log as well */ + if (*set->log_path == '\0') + i_syslog_fatal_handler(type, status, format, args); + else + default_fatal_handler(type, status, format, args); +} + +static void fatal_log_check(void) +{ + const struct settings *set = settings_root->defaults; + const char *path; + char buf[1024]; + ssize_t ret; + int fd; + + path = t_strconcat(set->base_dir, "/"FATAL_FILENAME, NULL); + fd = open(path, O_RDONLY); + if (fd == -1) + return; + + ret = read(fd, buf, sizeof(buf)); + if (ret < 0) + i_error("read(%s) failed: %m", path); + else { + buf[ret] = '\0'; + i_warning("Last died with error (see error log for more " + "information): %s", buf); + } + + close(fd); + if (unlink(path) < 0) + i_error("unlink(%s) failed: %m", path); +} + static void set_logfile(struct settings *set) { int facility; @@ -57,6 +110,7 @@ /* log to file or stderr */ i_set_failure_file(set->log_path, "dovecot: "); } + i_set_fatal_handler(master_fatal_callback); if (*set->info_log_path != '\0') i_set_info_file(set->info_log_path); @@ -492,6 +546,7 @@ if (!log_error) open_fds(); + fatal_log_check(); if (!foreground) daemonize(settings_root->defaults);