diff --git a/src/compton.c b/src/compton.c index 514a8fc..b75689f 100644 --- a/src/compton.c +++ b/src/compton.c @@ -2654,12 +2654,12 @@ session_init(session_t *ps_old, int argc, char **argv) { }; log_init_tls(); - struct log_target *log_target = stderr_logger_new(); - if (!log_target) { + auto stderr_logger = stderr_logger_new(); + if (!stderr_logger) { fprintf(stderr, "Cannot create any logger, giving up.\n"); abort(); } - log_add_target_tls(log_target); + log_add_target_tls(stderr_logger); // Allocate a session and copy default values into it session_t *ps = cmalloc(session_t); @@ -2788,14 +2788,11 @@ session_init(session_t *ps_old, int argc, char **argv) { get_cfg(&ps->o, argc, argv, shadow_enabled, fading_enable, hasneg, winopt_mask); if (ps->o.logpath) { - log_target = file_logger_new(ps->o.logpath); - if (log_target) { - auto level = log_get_level_tls(); + auto l = file_logger_new(ps->o.logpath); + if (l) { log_info("Switching to log file: %s", ps->o.logpath); - log_deinit_tls(); - log_init_tls(); - log_set_level_tls(level); - log_add_target_tls(log_target); + log_remove_target_tls(stderr_logger); + log_add_target_tls(l); } else { log_error("Failed to setup log file %s, I will keep using stderr", ps->o.logpath); } diff --git a/src/log.c b/src/log.c index 2fa4720..e79e910 100644 --- a/src/log.c +++ b/src/log.c @@ -103,7 +103,22 @@ void log_add_target(struct log *l, struct log_target *tgt) { l->head = tgt; } -/// Destroy a log struct +/// Remove a previously added log target for a log struct. If the log target was never +/// added, nothing happens. +void log_remove_target(struct log *l, struct log_target *tgt) { + struct log_target *now = l->head, **prev = &l->head; + while (now) { + if (now == tgt) { + *prev = now->next; + tgt->ops->destroy(tgt); + break; + } + prev = &now->next; + now = now->next; + } +} + +/// Destroy a log struct and every log target added to it void log_destroy(struct log *l) { // free all tgt struct log_target *head = l->head; diff --git a/src/log.h b/src/log.h index 4bd4a3c..d2e80a6 100644 --- a/src/log.h +++ b/src/log.h @@ -17,12 +17,11 @@ enum log_level { LOG_LEVEL_FATAL, }; -#define LOG(level, x, ...) \ - do { \ - if (LOG_LEVEL_##level >= log_get_level_tls()) { \ - log_printf(tls_logger, LOG_LEVEL_##level, __func__, x, \ - ##__VA_ARGS__); \ - } \ +#define LOG(level, x, ...) \ + do { \ + if (LOG_LEVEL_##level >= log_get_level_tls()) { \ + log_printf(tls_logger, LOG_LEVEL_##level, __func__, x, ##__VA_ARGS__); \ + } \ } while (0) #define log_trace(x, ...) LOG(TRACE, x, ##__VA_ARGS__) #define log_debug(x, ...) LOG(DEBUG, x, ##__VA_ARGS__) @@ -38,11 +37,15 @@ attr_printf(4, 5) void log_printf(struct log *, int level, const char *func, const char *fmt, ...); attr_malloc struct log *log_new(void); +/// Destroy a log struct and every log target added to it attr_nonnull_all void log_destroy(struct log *); attr_nonnull(1) void log_set_level(struct log *l, int level); attr_pure enum log_level log_get_level(const struct log *l); attr_nonnull_all void log_add_target(struct log *, struct log_target *); attr_const enum log_level string_to_log_level(const char *); +/// Remove a previously added log target for a log struct, and destroy it. If the log +/// target was never added, nothing happens. +void log_remove_target(struct log *l, struct log_target *tgt); extern thread_local struct log *tls_logger; @@ -60,6 +63,11 @@ static inline attr_nonnull_all void log_add_target_tls(struct log_target *tgt) { log_add_target(tls_logger, tgt); } +static inline attr_nonnull_all void log_remove_target_tls(struct log_target *tgt) { + assert(tls_logger); + log_remove_target(tls_logger, tgt); +} + static inline attr_pure enum log_level log_get_level_tls(void) { assert(tls_logger); return log_get_level(tls_logger);