]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
master: Write all the early warnings to log file after logging is initialized
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 5 Sep 2017 17:42:31 +0000 (20:42 +0300)
committerAki Tuomi <aki.tuomi@dovecot.fi>
Thu, 7 Sep 2017 11:12:49 +0000 (14:12 +0300)
Any warnings (or errors) logged before settings were read and logging was
initialized caused them to be only written to stderr. This caused them to
be lost too easily. Now they are also buffered in memory and then flushed
to log files once logging is initialized.

src/master/main.c

index c19d9a7d395fe53efc9ddff37f84eb85abeac330..d51c597edfa92805c001ca87c33b78525bcc8ebc 100644 (file)
 #define MASTER_PID_FILE_NAME "master.pid"
 #define SERVICE_TIME_MOVED_BACKWARDS_MAX_THROTTLE_SECS (60*3)
 
+struct master_delayed_error {
+       enum log_type type;
+       const char *line;
+};
+
 uid_t master_uid;
 gid_t master_gid;
 bool core_dumps_disabled;
@@ -50,6 +55,9 @@ bool startup_finished = FALSE;
 static char *pidfile_path;
 static struct master_instance_list *instances;
 static struct timeout *to_instance;
+
+static ARRAY(struct master_delayed_error) delayed_errors;
+static pool_t delayed_errors_pool;
 static failure_callback_t *orig_fatal_callback;
 static failure_callback_t *orig_error_callback;
 
@@ -182,6 +190,44 @@ startup_error_handler(const struct failure_context *ctx,
        orig_error_callback(ctx, fmt, args);
 }
 
+static void ATTR_FORMAT(2, 0)
+startup_early_error_handler(const struct failure_context *ctx,
+                           const char *fmt, va_list args)
+{
+       struct master_delayed_error *err;
+       va_list args2;
+
+       VA_COPY(args2, args);
+       if (delayed_errors_pool == NULL) {
+               delayed_errors_pool =
+                       pool_alloconly_create("delayed errors", 512);
+               i_array_init(&delayed_errors, 8);
+       }
+       err = array_append_space(&delayed_errors);
+       err->type = ctx->type;
+       err->line = p_strdup_vprintf(delayed_errors_pool, fmt, args2);
+       va_end(args2);
+
+       orig_error_callback(ctx, fmt, args);
+}
+
+static void startup_early_errors_flush(void)
+{
+       struct failure_context ctx;
+       const struct master_delayed_error *err;
+
+       if (delayed_errors_pool == NULL)
+               return;
+
+       i_zero(&ctx);
+       array_foreach(&delayed_errors, err) {
+               ctx.type = err->type;
+               i_log_type(&ctx, "%s", err->line);
+       }
+       array_free(&delayed_errors);
+       pool_unref(&delayed_errors_pool);
+}
+
 static void fatal_log_check(const struct master_settings *set)
 {
        const char *path;
@@ -720,6 +766,10 @@ int main(int argc, char *argv[])
                                &argc, &argv, "+Fanp");
        i_unset_failure_prefix();
 
+       i_get_failure_handlers(&orig_fatal_callback, &orig_error_callback,
+                              &orig_info_callback, &orig_debug_callback);
+       i_set_error_handler(startup_early_error_handler);
+
        io_loop_set_time_moved_callback(current_ioloop, master_time_moved);
 
        master_uid = geteuid();
@@ -811,6 +861,7 @@ int main(int argc, char *argv[])
                i_strconcat(set->base_dir, "/"MASTER_PID_FILE_NAME, NULL);
 
        master_service_init_log(master_service, "master: ");
+       startup_early_errors_flush();
        i_get_failure_handlers(&orig_fatal_callback, &orig_error_callback,
                               &orig_info_callback, &orig_debug_callback);
        i_set_fatal_handler(startup_fatal_handler);