From: Martin Mares Date: Tue, 4 Feb 2014 12:55:23 +0000 (+0100) Subject: Logging: Stream filters are permitted to modify log messages X-Git-Tag: v6.0~70^2 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=e1b297303866e8a2f7611515a7e90fba483c7000;p=libucw.git Logging: Stream filters are permitted to modify log messages --- diff --git a/maint/libucw.abi b/maint/libucw.abi index cd462cc2..c11f2404 100644 --- a/maint/libucw.abi +++ b/maint/libucw.abi @@ -292,6 +292,7 @@ log_set_format log_stream_by_flags log_set_default_stream log_close_all +log_pass_filtered log_new_file log_new_fd log_switch_disable diff --git a/ucw/log-conf.c b/ucw/log-conf.c index 824d95fc..ff71feaa 100644 --- a/ucw/log-conf.c +++ b/ucw/log-conf.c @@ -243,7 +243,7 @@ log_limiter(struct log_stream *ls, struct log_msg *m) struct log_msg mm = *m; mm.flags |= L_LOGGER_ERR; mm.raw_msg = "(maximum logging rate exceeded, some messages will be suppressed)"; - log_pass_msg(0, ls, &mm); + log_pass_msg(ls, &mm); } return 1; } diff --git a/ucw/log-internal.h b/ucw/log-internal.h index c2eef05b..dc1d1526 100644 --- a/ucw/log-internal.h +++ b/ucw/log-internal.h @@ -19,13 +19,8 @@ #define log_type_names ucw_log_type_names #endif -/* - * Pass a message to a stream. - * @depth prevents loops. - * Returns 1 in case of loop detection or other fatal error, - * 0 otherwise - */ -int log_pass_msg(int depth, struct log_stream *ls, struct log_msg *m); +/* Pass a message to a stream. */ +void log_pass_msg(struct log_stream *ls, struct log_msg *m); /* Define an array (growing buffer) for pointers to log_streams. */ #define GBUF_TYPE struct log_stream* diff --git a/ucw/log.c b/ucw/log.c index df6eae05..aea97e3b 100644 --- a/ucw/log.c +++ b/ucw/log.c @@ -161,10 +161,11 @@ vmsg(uns cat, const char *fmt, va_list args) } /* Pass the message to the log_stream */ - if (log_pass_msg(0, ls, &m)) + log_pass_msg(ls, &m); + if (m.error) { /* Error (such as infinite loop) occurred */ - log_pass_msg(0, &log_stream_default, &m); + log_pass_msg(&log_stream_default, &m); } if (m.raw_msg != msgbuf) @@ -194,7 +195,7 @@ log_report_err(struct log_stream *ls, struct log_msg *m, int err) errno = err; snprintf(errbuf, sizeof(errbuf), "Error logging to %s: %m", name); } - log_pass_msg(0, &log_stream_default, &errm); + log_pass_msg(&log_stream_default, &errm); if (ls->stream_flags & LSFLAG_ERR_IS_FATAL) do_die(); @@ -203,32 +204,20 @@ log_report_err(struct log_stream *ls, struct log_msg *m, int err) /* Maximal depth of log_pass_msg recursion */ #define LS_MAX_DEPTH 64 -int -log_pass_msg(int depth, struct log_stream *ls, struct log_msg *m) +void +log_pass_filtered(struct log_stream *ls, struct log_msg *m) { - ASSERT(ls); - - /* Check recursion depth */ - if (depth > LS_MAX_DEPTH) - { - log_report_err(ls, m, EDEADLK); - return 1; - } - - /* Filter by level, type and hook function */ - if (!((1 << LS_GET_LEVEL(m->flags)) & ls->levels) || - !((1 << LS_GET_TYPE(m->flags)) & ls->types) || - ls->filter && ls->filter(ls, m)) - return 0; - /* Pass the message to substreams */ CLIST_FOR_EACH(simp_node *, s, ls->substreams) - if (log_pass_msg(depth+1, s->p, m)) - return 1; + { + log_pass_msg(s->p, m); + if (m->error) + return; + } /* Will pass to the handler of this stream... is there any? */ if (!ls->handler) - return 0; + return; /* Will print a message type? */ char *type = NULL; @@ -316,7 +305,36 @@ log_pass_msg(int depth, struct log_stream *ls, struct log_msg *m) if (free_buf) xfree(free_buf); - return 0; +} + +void +log_pass_msg(struct log_stream *ls, struct log_msg *m) +{ + ASSERT(ls); + + /* Check recursion depth */ + if (m->depth > LS_MAX_DEPTH) + { + log_report_err(ls, m, EDEADLK); + m->error = 1; + return; + } + + /* Filter by level and type */ + if (!((1 << LS_GET_LEVEL(m->flags)) & ls->levels) || + !((1 << LS_GET_TYPE(m->flags)) & ls->types)) + return; + + m->depth++; + + if (ls->filter && ls->filter(ls, m)) + { + // The filter might have called log_pass_filtered() + } + else + log_pass_filtered(ls, m); + + m->depth--; } /*** Utility functions ***/ diff --git a/ucw/log.h b/ucw/log.h index d4cc525d..bee7a8a2 100644 --- a/ucw/log.h +++ b/ucw/log.h @@ -25,6 +25,7 @@ #define log_new_file ucw_log_new_file #define log_new_stream ucw_log_new_stream #define log_new_syslog ucw_log_new_syslog +#define log_pass_filtered ucw_log_pass_filtered #define log_register_type ucw_log_register_type #define log_rm_substream ucw_log_rm_substream #define log_set_default_stream ucw_log_set_default_stream @@ -51,6 +52,8 @@ struct log_msg { char *raw_msg; // Unformatted parts char *stime; char *sutime; + uns depth; // Recursion depth + bool error; // An error has occurred (e.g., an infinite loop in sub-streams) }; /** @@ -220,6 +223,15 @@ void log_set_default_stream(struct log_stream *ls); **/ void log_close_all(void); +/** + * The filter function of a stream might want to modify the message + * before passing it to the handler and/or substreams. In this case, + * the filter should make a local copy of `struct log_msg`, call + * @log_pass_filtered() on it and return true, so that the original + * message will not be processed any further. + **/ +void log_pass_filtered(struct log_stream *ls, struct log_msg *m); + /*** * === Logging to files *