g_log_set_always_fatal() and unexpected behavior for uncofigured log domains
Submitted by Marcelo Vanzin
Link to original bug (#619048)
Description
If a specific domain hasn't been configured (so that the default log handler is triggered), the glib code currently forces G_LOG_FATAL_MASK onto that domain; so there's no way to globally disable some flag that is part of G_LOG_FATAL_MASK.
Consider the following code:
=============== CUT ===============
#include <glib.h> #include <stdio.h>
#undef G_LOG_DOMAIN #define G_LOG_DOMAIN "rec1" void mylog(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { printf("mylog: %s:%d: %s\n", log_domain, log_level, message); if (!(log_level & G_LOG_FLAG_RECURSION)) { g_debug("recursing\n"); } }
void rec1(void) { g_warning("log message 1"); }
#undef G_LOG_DOMAIN #define G_LOG_DOMAIN "rec2" void mylog2(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { printf("mylog2: %s:%d: %s\n", log_domain, log_level, message); if (!(log_level & G_LOG_FLAG_RECURSION)) { g_debug("recursing\n"); } }
void rec2(void) { g_warning("log message 2"); }
int main(void) { g_log_set_always_fatal(G_LOG_LEVEL_ERROR); g_log_set_fatal_mask("rec1", G_LOG_LEVEL_ERROR); g_log_set_default_handler(mylog2, NULL); g_log_set_handler("rec1", 0XFFFF, mylog, NULL); rec1(); rec2(); return 0; }
=============== /CUT ===============
The "rec1" domain is configured and doesn't crash when you force log recursion. The "rec2" domain is not configured, and even though I disabled crashing on recursion using g_log_set_always_fatal(), it is ignored:
$ ./rec mylog: rec1:16: log message 1
(process:31613): rec1-DEBUG (recursed): recursing
mylog2: rec2:16: log message 2
(process:31613): rec2-DEBUG (recursed): recursing
aborting... Aborted
This code in gmessages.c is probably to blame:
domain_fatal_mask = domain ? domain->fatal_mask : G_LOG_FATAL_MASK;
Instead of G_LOG_FATAL_MASK, it should probably be using 'g_log_always_fatal', which is the variable set by g_log_set_always_fatal(), or "0" (since the mask is or'ed with g_log_always_fatal later).