changeset 12275:4933c3095ee2

Cleaned up log callbacks and made them more extensible. fatal_failure_callback_t type is now gone, there's only failure_callback_t left that has a struct pointer as parameter. More parameters can be easily added to the struct in future.
author Timo Sirainen <tss@iki.fi>
date Fri, 15 Oct 2010 15:46:43 +0100
parents b0e4edc4d79a
children e68366e88099
files src/doveadm/doveadm-log.c src/lib-test/test-common.c src/lib/failures.c src/lib/failures.h src/log/log-connection.c src/master/main.c
diffstat 6 files changed, 119 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/src/doveadm/doveadm-log.c	Fri Oct 15 15:13:59 2010 +0100
+++ b/src/doveadm/doveadm-log.c	Fri Oct 15 15:46:43 2010 +0100
@@ -21,17 +21,20 @@
 
 static void cmd_log_test(int argc ATTR_UNUSED, char *argv[] ATTR_UNUSED)
 {
+	struct failure_context ctx;
 	unsigned int i;
 
 	master_service->flags |= MASTER_SERVICE_FLAG_DONT_LOG_TO_STDERR;
 	master_service_init_log(master_service, "doveadm: ");
 
+	memset(&ctx, 0, sizeof(ctx));
 	for (i = 0; i < LAST_LOG_TYPE; i++) {
 		const char *prefix = failure_log_type_prefixes[i];
 
 		/* add timestamp so that syslog won't just write
 		   "repeated message" text */
-		i_log_type(i, TEST_LOG_MSG_PREFIX"%s log (%u)",
+		ctx.type = i;
+		i_log_type(&ctx, TEST_LOG_MSG_PREFIX"%s log (%u)",
 			   t_str_lcase(t_strcut(prefix, ':')),
 			   (unsigned int)ioloop_time);
 	}
--- a/src/lib-test/test-common.c	Fri Oct 15 15:13:59 2010 +0100
+++ b/src/lib-test/test-common.c	Fri Oct 15 15:46:43 2010 +0100
@@ -186,11 +186,13 @@
 }
 
 static void
-test_error_handler(enum log_type type, const char *format, va_list args)
+test_error_handler(const struct failure_context *ctx,
+		   const char *format, va_list args)
 {
-	default_error_handler(type, format, args);
+	default_error_handler(ctx, format, args);
 #ifdef DEBUG
-	if (type == LOG_TYPE_WARNING && strstr(format, "Growing") != NULL) {
+	if (ctx->type == LOG_TYPE_WARNING &&
+	    strstr(format, "Growing") != NULL) {
 		/* ignore "Growing memory pool" and "Growing data stack"
 		   warnings */
 		return;
--- a/src/lib/failures.c	Fri Oct 15 15:13:59 2010 +0100
+++ b/src/lib/failures.c	Fri Oct 15 15:46:43 2010 +0100
@@ -27,20 +27,26 @@
 };
 
 /* Initialize working defaults */
-static fatal_failure_callback_t *fatal_handler ATTR_NORETURN =
+static failure_callback_t *fatal_handler ATTR_NORETURN =
 	default_fatal_handler;
 static failure_callback_t *error_handler = default_error_handler;
 static failure_callback_t *info_handler = default_error_handler;
 static failure_callback_t *debug_handler = default_error_handler;
 static void (*failure_exit_callback)(int *) = NULL;
 
+static struct failure_context failure_ctx_debug = { .type = LOG_TYPE_DEBUG };
+static struct failure_context failure_ctx_info = { .type = LOG_TYPE_INFO };
+static struct failure_context failure_ctx_warning = { .type = LOG_TYPE_WARNING };
+static struct failure_context failure_ctx_error = { .type = LOG_TYPE_ERROR };
+
 static int log_fd = STDERR_FILENO, log_info_fd = STDERR_FILENO,
 	   log_debug_fd = STDERR_FILENO;
 static char *log_prefix = NULL, *log_stamp_format = NULL;
 static bool failure_ignore_errors = FALSE;
 
 static void ATTR_FORMAT(2, 0)
-i_internal_error_handler(enum log_type type, const char *fmt, va_list args);
+i_internal_error_handler(const struct failure_context *ctx,
+			 const char *format, va_list args);
 
 /* kludgy .. we want to trust log_stamp_format with -Wformat-nonliteral */
 static const char *get_log_stamp_format(const char *unused)
@@ -180,21 +186,25 @@
 		failure_exit(status);
 }
 
-void default_fatal_handler(enum log_type type, int status,
+void default_fatal_handler(const struct failure_context *ctx,
 			   const char *format, va_list args)
 {
-	if (default_handler(failure_log_type_prefixes[type], log_fd, format,
-			    args) < 0 && status == FATAL_DEFAULT)
+	int status = ctx->exit_status;
+
+	if (default_handler(failure_log_type_prefixes[ctx->type],
+			    log_fd, format, args) < 0 &&
+	    status == FATAL_DEFAULT)
 		status = FATAL_LOGWRITE;
 
-	default_fatal_finish(type, status);
+	default_fatal_finish(ctx->type, status);
 }
 
-void default_error_handler(enum log_type type, const char *format, va_list args)
+void default_error_handler(const struct failure_context *ctx,
+			   const char *format, va_list args)
 {
 	int fd;
 
-	switch (type) {
+	switch (ctx->type) {
 	case LOG_TYPE_DEBUG:
 		fd = log_debug_fd;
 		break;
@@ -205,7 +215,7 @@
 		fd = log_fd;
 	}
 
-	if (default_handler(failure_log_type_prefixes[type],
+	if (default_handler(failure_log_type_prefixes[ctx->type],
 			    fd, format, args) < 0) {
 		if (fd == log_fd)
 			failure_exit(FATAL_LOGWRITE);
@@ -216,21 +226,21 @@
 	}
 }
 
-void i_log_type(enum log_type type, const char *format, ...)
+void i_log_type(const struct failure_context *ctx, const char *format, ...)
 {
 	va_list args;
 
 	va_start(args, format);
 
-	switch (type) {
+	switch (ctx->type) {
 	case LOG_TYPE_DEBUG:
-		debug_handler(type, format, args);
+		debug_handler(ctx, format, args);
 		break;
 	case LOG_TYPE_INFO:
-		info_handler(type, format, args);
+		info_handler(ctx, format, args);
 		break;
 	default:
-		error_handler(type, format, args);
+		error_handler(ctx, format, args);
 	}
 
 	va_end(args);
@@ -238,28 +248,42 @@
 
 void i_panic(const char *format, ...)
 {
+	struct failure_context ctx;
 	va_list args;
 
+	memset(&ctx, 0, sizeof(ctx));
+	ctx.type = LOG_TYPE_PANIC;
+
 	va_start(args, format);
-	fatal_handler(LOG_TYPE_PANIC, 0, format, args);
+	fatal_handler(&ctx, format, args);
 	va_end(args);
 }
 
 void i_fatal(const char *format, ...)
 {
+	struct failure_context ctx;
 	va_list args;
 
+	memset(&ctx, 0, sizeof(ctx));
+	ctx.type = LOG_TYPE_FATAL;
+	ctx.exit_status = FATAL_DEFAULT;
+
 	va_start(args, format);
-	fatal_handler(LOG_TYPE_FATAL, FATAL_DEFAULT, format, args);
+	fatal_handler(&ctx, format, args);
 	va_end(args);
 }
 
 void i_fatal_status(int status, const char *format, ...)
 {
+	struct failure_context ctx;
 	va_list args;
 
+	memset(&ctx, 0, sizeof(ctx));
+	ctx.type = LOG_TYPE_FATAL;
+	ctx.exit_status = status;
+
 	va_start(args, format);
-	fatal_handler(LOG_TYPE_FATAL, status, format, args);
+	fatal_handler(&ctx, format, args);
 	va_end(args);
 }
 
@@ -269,7 +293,7 @@
 	va_list args;
 
 	va_start(args, format);
-	error_handler(LOG_TYPE_ERROR, format, args);
+	error_handler(&failure_ctx_error, format, args);
 	va_end(args);
 
 	errno = old_errno;
@@ -281,7 +305,7 @@
 	va_list args;
 
 	va_start(args, format);
-	error_handler(LOG_TYPE_WARNING, format, args);
+	error_handler(&failure_ctx_warning, format, args);
 	va_end(args);
 
 	errno = old_errno;
@@ -293,7 +317,7 @@
 	va_list args;
 
 	va_start(args, format);
-	info_handler(LOG_TYPE_INFO, format, args);
+	info_handler(&failure_ctx_info, format, args);
 	va_end(args);
 
 	errno = old_errno;
@@ -305,13 +329,13 @@
 	va_list args;
 
 	va_start(args, format);
-	debug_handler(LOG_TYPE_DEBUG, format, args);
+	debug_handler(&failure_ctx_debug, format, args);
 	va_end(args);
 
 	errno = old_errno;
 }
 
-void i_set_fatal_handler(fatal_failure_callback_t *callback ATTR_NORETURN)
+void i_set_fatal_handler(failure_callback_t *callback ATTR_NORETURN)
 {
 	if (callback == NULL)
 		callback = default_fatal_handler;
@@ -339,7 +363,7 @@
 	debug_handler = callback;
 }
 
-void i_get_failure_handlers(fatal_failure_callback_t **fatal_callback_r,
+void i_get_failure_handlers(failure_callback_t **fatal_callback_r,
 			    failure_callback_t **error_callback_r,
 			    failure_callback_t **info_callback_r,
 			    failure_callback_t **debug_callback_r)
@@ -372,21 +396,24 @@
 	return 0;
 }
 
-void i_syslog_fatal_handler(enum log_type type, int status,
-			    const char *fmt, va_list args)
+void i_syslog_fatal_handler(const struct failure_context *ctx,
+			    const char *format, va_list args)
 {
-	if (syslog_handler(LOG_CRIT, type, fmt, args) < 0 &&
+	int status = ctx->exit_status;
+
+	if (syslog_handler(LOG_CRIT, ctx->type, format, args) < 0 &&
 	    status == FATAL_DEFAULT)
 		status = FATAL_LOGERROR;
 
-	default_fatal_finish(type, status);
+	default_fatal_finish(ctx->type, status);
 }
 
-void i_syslog_error_handler(enum log_type type, const char *fmt, va_list args)
+void i_syslog_error_handler(const struct failure_context *ctx,
+			    const char *format, va_list args)
 {
 	int level = LOG_ERR;
 
-	switch (type) {
+	switch (ctx->type) {
 	case LOG_TYPE_DEBUG:
 		level = LOG_DEBUG;
 		break;
@@ -408,7 +435,7 @@
 		i_unreached();
 	}
 
-	if (syslog_handler(level, type, fmt, args) < 0)
+	if (syslog_handler(level, ctx->type, format, args) < 0)
 		failure_exit(FATAL_LOGERROR);
 }
 
@@ -511,7 +538,8 @@
 		str_truncate(str, prefix_len);
 		str_append_n(str, str_c(full_str) + pos, max_text_len);
 		str_append_c(str, '\n');
-		if (log_fd_write(2, str_data(str), str_len(str)) < 0)
+		if (log_fd_write(STDERR_FILENO,
+				 str_data(str), str_len(str)) < 0)
 			return -1;
 		pos += max_text_len;
 	}
@@ -519,7 +547,8 @@
 }
 
 static int ATTR_FORMAT(2, 0)
-internal_handler(enum log_type log_type, const char *format, va_list args)
+internal_handler(const struct failure_context *ctx,
+		 const char *format, va_list args)
 {
 	static int recursed = 0;
 	int ret;
@@ -536,13 +565,14 @@
 		unsigned int prefix_len;
 
 		str = t_str_new(128);
-		str_printfa(str, "\001%c%s ", log_type + 1, my_pid);
+		str_printfa(str, "\001%c%s ", ctx->type + 1, my_pid);
 		prefix_len = str_len(str);
 
 		str_vprintfa(str, format, args);
 		if (str_len(str)+1 <= PIPE_BUF) {
 			str_append_c(str, '\n');
-			ret = log_fd_write(2, str_data(str), str_len(str));
+			ret = log_fd_write(STDERR_FILENO,
+					   str_data(str), str_len(str));
 		} else {
 			ret = internal_send_split(str, prefix_len);
 		}
@@ -596,21 +626,24 @@
 	failure->text = line + 1;
 }
 
-static void ATTR_NORETURN ATTR_FORMAT(3, 0)
-i_internal_fatal_handler(enum log_type type, int status,
-			 const char *fmt, va_list args)
+static void ATTR_NORETURN ATTR_FORMAT(2, 0)
+i_internal_fatal_handler(const struct failure_context *ctx,
+			 const char *format, va_list args)
 {
-	if (internal_handler(type, fmt, args) < 0 &&
+	int status = ctx->exit_status;
+
+	if (internal_handler(ctx, format, args) < 0 &&
 	    status == FATAL_DEFAULT)
 		status = FATAL_LOGERROR;
 
-	default_fatal_finish(type, status);
+	default_fatal_finish(ctx->type, status);
 }
 
 static void
-i_internal_error_handler(enum log_type type, const char *fmt, va_list args)
+i_internal_error_handler(const struct failure_context *ctx,
+			 const char *format, va_list args)
 {
-	if (internal_handler(type, fmt, args) < 0)
+	if (internal_handler(ctx, format, args) < 0)
 		failure_exit(FATAL_LOGERROR);
 }
 
--- a/src/lib/failures.h	Fri Oct 15 15:13:59 2010 +0100
+++ b/src/lib/failures.h	Fri Oct 15 15:46:43 2010 +0100
@@ -32,15 +32,20 @@
 	const char *text;
 };
 
+struct failure_context {
+	enum log_type type;
+	int exit_status; /* for LOG_TYPE_FATAL */
+};
+
 #define DEFAULT_FAILURE_STAMP_FORMAT "%b %d %H:%M:%S "
 
-typedef void failure_callback_t(enum log_type type, const char *, va_list);
-typedef void fatal_failure_callback_t(enum log_type type, int status,
-				      const char *, va_list);
+typedef void failure_callback_t(const struct failure_context *ctx,
+				const char *format, va_list args);
 
 extern const char *failure_log_type_prefixes[];
 
-void i_log_type(enum log_type type, const char *format, ...) ATTR_FORMAT(2, 3);
+void i_log_type(const struct failure_context *ctx, const char *format, ...)
+	ATTR_FORMAT(2, 3);
 
 void i_panic(const char *format, ...) ATTR_FORMAT(1, 2) ATTR_NORETURN ATTR_COLD;
 void i_fatal(const char *format, ...) ATTR_FORMAT(1, 2) ATTR_NORETURN ATTR_COLD;
@@ -54,31 +59,33 @@
 
 /* Change failure handlers. */
 #ifndef __cplusplus
-void i_set_fatal_handler(fatal_failure_callback_t *callback ATTR_NORETURN);
+void i_set_fatal_handler(failure_callback_t *callback ATTR_NORETURN);
 #else
 /* Older g++ doesn't like attributes in parameters */
-void i_set_fatal_handler(fatal_failure_callback_t *callback);
+void i_set_fatal_handler(failure_callback_t *callback);
 #endif
 void i_set_error_handler(failure_callback_t *callback);
 void i_set_info_handler(failure_callback_t *callback);
 void i_set_debug_handler(failure_callback_t *callback);
-void i_get_failure_handlers(fatal_failure_callback_t **fatal_callback_r,
+void i_get_failure_handlers(failure_callback_t **fatal_callback_r,
 			    failure_callback_t **error_callback_r,
 			    failure_callback_t **info_callback_r,
 			    failure_callback_t **debug_callback_r);
 
 /* Send failures to file. */
-void default_fatal_handler(enum log_type type, int status,
+void default_fatal_handler(const struct failure_context *ctx,
 			   const char *format, va_list args)
-	ATTR_NORETURN ATTR_FORMAT(3, 0);
-void default_error_handler(enum log_type type, const char *format, va_list args)
+	ATTR_NORETURN ATTR_FORMAT(2, 0);
+void default_error_handler(const struct failure_context *ctx,
+			   const char *format, va_list args)
 	ATTR_FORMAT(2, 0);
 
 /* Send failures to syslog() */
-void i_syslog_fatal_handler(enum log_type type, int status,
-			    const char *fmt, va_list args)
-	ATTR_NORETURN ATTR_FORMAT(3, 0);
-void i_syslog_error_handler(enum log_type type, const char *fmt, va_list args)
+void i_syslog_fatal_handler(const struct failure_context *ctx,
+			    const char *format, va_list args)
+	ATTR_NORETURN ATTR_FORMAT(2, 0);
+void i_syslog_error_handler(const struct failure_context *ctx,
+			    const char *format, va_list args)
 	ATTR_FORMAT(2, 0);
 
 /* Open syslog and set failure/info/debug handlers to use it. */
--- a/src/log/log-connection.c	Fri Oct 15 15:13:59 2010 +0100
+++ b/src/log/log-connection.c	Fri Oct 15 15:46:43 2010 +0100
@@ -125,6 +125,7 @@
 static void log_it(struct log_connection *log, const char *line)
 {
 	struct failure_line failure;
+	struct failure_context failure_ctx;
 	struct log_client *client = NULL;
 	const char *prefix;
 
@@ -150,10 +151,13 @@
 	}
 	i_assert(failure.log_type < LOG_TYPE_COUNT);
 
+	memset(&failure_ctx, 0, sizeof(failure_ctx));
+	failure_ctx.type = failure.log_type;
+
 	prefix = client != NULL && client->prefix != NULL ?
 		client->prefix : log->default_prefix;
 	i_set_failure_prefix(prefix);
-	i_log_type(failure.log_type, "%s", failure.text);
+	i_log_type(&failure_ctx, "%s", failure.text);
 	i_set_failure_prefix("log: ");
 }
 
--- a/src/master/main.c	Fri Oct 15 15:13:59 2010 +0100
+++ b/src/master/main.c	Fri Oct 15 15:46:43 2010 +0100
@@ -46,7 +46,7 @@
 struct service_list *services;
 
 static char *pidfile_path;
-static fatal_failure_callback_t *orig_fatal_callback;
+static failure_callback_t *orig_fatal_callback;
 static failure_callback_t *orig_error_callback;
 static const char *child_process_env[3]; /* @UNSAFE */
 
@@ -125,7 +125,7 @@
 }
 
 static void ATTR_NORETURN ATTR_FORMAT(3, 0)
-master_fatal_callback(enum log_type type, int status,
+master_fatal_callback(const struct failure_context *ctx,
 		      const char *format, va_list args)
 {
 	const char *path, *str;
@@ -147,32 +147,33 @@
 		}
 	}
 
-	orig_fatal_callback(type, status, format, args);
+	orig_fatal_callback(ctx, format, args);
 	abort(); /* just to silence the noreturn attribute warnings */
 }
 
 static void ATTR_NORETURN
-startup_fatal_handler(enum log_type type, int status,
+startup_fatal_handler(const struct failure_context *ctx,
 		      const char *fmt, va_list args)
 {
 	va_list args2;
 
 	VA_COPY(args2, args);
-	fprintf(stderr, "%s%s\n", failure_log_type_prefixes[type],
+	fprintf(stderr, "%s%s\n", failure_log_type_prefixes[ctx->type],
 		t_strdup_vprintf(fmt, args2));
-	orig_fatal_callback(type, status, fmt, args);
+	orig_fatal_callback(ctx, fmt, args);
 	abort();
 }
 
 static void
-startup_error_handler(enum log_type type, const char *fmt, va_list args)
+startup_error_handler(const struct failure_context *ctx,
+		      const char *fmt, va_list args)
 {
 	va_list args2;
 
 	VA_COPY(args2, args);
-	fprintf(stderr, "%s%s\n", failure_log_type_prefixes[type],
+	fprintf(stderr, "%s%s\n", failure_log_type_prefixes[ctx->type],
 		t_strdup_vprintf(fmt, args2));
-	orig_error_callback(type, fmt, args);
+	orig_error_callback(ctx, fmt, args);
 }
 
 static void fatal_log_check(const struct master_settings *set)