diff options
author | Tim Janik <timj@gtk.org> | 2002-03-27 17:57:30 +0000 |
---|---|---|
committer | Tim Janik <timj@src.gnome.org> | 2002-03-27 17:57:30 +0000 |
commit | f4d7817b139f2bd0915afff141e23d76fcb05a9c (patch) | |
tree | 567db8d574922c176e1b4275354595d99c5fffd1 | |
parent | 564cbf8516604f18cb2d4c2f9417e6ff7e2933d7 (diff) |
major cleanups. introduced _g_log_fallback_handler() to handle recursive
Wed Mar 27 18:42:22 2002 Tim Janik <timj@gtk.org>
* gmessages.[hc]:
major cleanups. introduced _g_log_fallback_handler() to handle
recursive messages which really doesn't call any GLib functions.
this allowes the default handler to use normal GLib functions and
also fixes user supplied log level handlers.
fixed locking issues, based on a patch from Sebastian Willhelmi,
attached to #74356. translate log messages from UTF-8, based
on the same patch. save fatal and recursion flags across flag
loop. use new integer format code from above patch.
move GLib functions out of locked mutex state to avoid deadlocks.
move the level prefix and filedescriptor logic into mklevel_prefix().
move _g_debug_init() into a place where we can figure and handle
recursion.
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 16 | ||||
-rw-r--r-- | ChangeLog.pre-2-12 | 16 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 16 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 16 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 16 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 16 | ||||
-rw-r--r-- | glib/gmessages.c | 714 | ||||
-rw-r--r-- | glib/gmessages.h | 7 |
9 files changed, 476 insertions, 357 deletions
@@ -1,3 +1,19 @@ +Wed Mar 27 18:42:22 2002 Tim Janik <timj@gtk.org> + + * gmessages.[hc]: + major cleanups. introduced _g_log_fallback_handler() to handle + recursive messages which really doesn't call any GLib functions. + this allowes the default handler to use normal GLib functions and + also fixes user supplied log level handlers. + fixed locking issues, based on a patch from Sebastian Willhelmi, + attached to #74356. translate log messages from UTF-8, based + on the same patch. save fatal and recursion flags across flag + loop. use new integer format code from above patch. + move GLib functions out of locked mutex state to avoid deadlocks. + move the level prefix and filedescriptor logic into mklevel_prefix(). + move _g_debug_init() into a place where we can figure and handle + recursion. + Mon Mar 25 18:13:06 2002 Owen Taylor <otaylor@redhat.com> * glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__ diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 6dfffb5cd..34947a7ef 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,19 @@ +Wed Mar 27 18:42:22 2002 Tim Janik <timj@gtk.org> + + * gmessages.[hc]: + major cleanups. introduced _g_log_fallback_handler() to handle + recursive messages which really doesn't call any GLib functions. + this allowes the default handler to use normal GLib functions and + also fixes user supplied log level handlers. + fixed locking issues, based on a patch from Sebastian Willhelmi, + attached to #74356. translate log messages from UTF-8, based + on the same patch. save fatal and recursion flags across flag + loop. use new integer format code from above patch. + move GLib functions out of locked mutex state to avoid deadlocks. + move the level prefix and filedescriptor logic into mklevel_prefix(). + move _g_debug_init() into a place where we can figure and handle + recursion. + Mon Mar 25 18:13:06 2002 Owen Taylor <otaylor@redhat.com> * glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__ diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 6dfffb5cd..34947a7ef 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,19 @@ +Wed Mar 27 18:42:22 2002 Tim Janik <timj@gtk.org> + + * gmessages.[hc]: + major cleanups. introduced _g_log_fallback_handler() to handle + recursive messages which really doesn't call any GLib functions. + this allowes the default handler to use normal GLib functions and + also fixes user supplied log level handlers. + fixed locking issues, based on a patch from Sebastian Willhelmi, + attached to #74356. translate log messages from UTF-8, based + on the same patch. save fatal and recursion flags across flag + loop. use new integer format code from above patch. + move GLib functions out of locked mutex state to avoid deadlocks. + move the level prefix and filedescriptor logic into mklevel_prefix(). + move _g_debug_init() into a place where we can figure and handle + recursion. + Mon Mar 25 18:13:06 2002 Owen Taylor <otaylor@redhat.com> * glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__ diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 6dfffb5cd..34947a7ef 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,19 @@ +Wed Mar 27 18:42:22 2002 Tim Janik <timj@gtk.org> + + * gmessages.[hc]: + major cleanups. introduced _g_log_fallback_handler() to handle + recursive messages which really doesn't call any GLib functions. + this allowes the default handler to use normal GLib functions and + also fixes user supplied log level handlers. + fixed locking issues, based on a patch from Sebastian Willhelmi, + attached to #74356. translate log messages from UTF-8, based + on the same patch. save fatal and recursion flags across flag + loop. use new integer format code from above patch. + move GLib functions out of locked mutex state to avoid deadlocks. + move the level prefix and filedescriptor logic into mklevel_prefix(). + move _g_debug_init() into a place where we can figure and handle + recursion. + Mon Mar 25 18:13:06 2002 Owen Taylor <otaylor@redhat.com> * glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__ diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 6dfffb5cd..34947a7ef 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,19 @@ +Wed Mar 27 18:42:22 2002 Tim Janik <timj@gtk.org> + + * gmessages.[hc]: + major cleanups. introduced _g_log_fallback_handler() to handle + recursive messages which really doesn't call any GLib functions. + this allowes the default handler to use normal GLib functions and + also fixes user supplied log level handlers. + fixed locking issues, based on a patch from Sebastian Willhelmi, + attached to #74356. translate log messages from UTF-8, based + on the same patch. save fatal and recursion flags across flag + loop. use new integer format code from above patch. + move GLib functions out of locked mutex state to avoid deadlocks. + move the level prefix and filedescriptor logic into mklevel_prefix(). + move _g_debug_init() into a place where we can figure and handle + recursion. + Mon Mar 25 18:13:06 2002 Owen Taylor <otaylor@redhat.com> * glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__ diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 6dfffb5cd..34947a7ef 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,19 @@ +Wed Mar 27 18:42:22 2002 Tim Janik <timj@gtk.org> + + * gmessages.[hc]: + major cleanups. introduced _g_log_fallback_handler() to handle + recursive messages which really doesn't call any GLib functions. + this allowes the default handler to use normal GLib functions and + also fixes user supplied log level handlers. + fixed locking issues, based on a patch from Sebastian Willhelmi, + attached to #74356. translate log messages from UTF-8, based + on the same patch. save fatal and recursion flags across flag + loop. use new integer format code from above patch. + move GLib functions out of locked mutex state to avoid deadlocks. + move the level prefix and filedescriptor logic into mklevel_prefix(). + move _g_debug_init() into a place where we can figure and handle + recursion. + Mon Mar 25 18:13:06 2002 Owen Taylor <otaylor@redhat.com> * glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__ diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 6dfffb5cd..34947a7ef 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,19 @@ +Wed Mar 27 18:42:22 2002 Tim Janik <timj@gtk.org> + + * gmessages.[hc]: + major cleanups. introduced _g_log_fallback_handler() to handle + recursive messages which really doesn't call any GLib functions. + this allowes the default handler to use normal GLib functions and + also fixes user supplied log level handlers. + fixed locking issues, based on a patch from Sebastian Willhelmi, + attached to #74356. translate log messages from UTF-8, based + on the same patch. save fatal and recursion flags across flag + loop. use new integer format code from above patch. + move GLib functions out of locked mutex state to avoid deadlocks. + move the level prefix and filedescriptor logic into mklevel_prefix(). + move _g_debug_init() into a place where we can figure and handle + recursion. + Mon Mar 25 18:13:06 2002 Owen Taylor <otaylor@redhat.com> * glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__ diff --git a/glib/gmessages.c b/glib/gmessages.c index 146670791..40e638993 100644 --- a/glib/gmessages.c +++ b/glib/gmessages.c @@ -80,15 +80,14 @@ static gsize printf_string_upper_bound (const gchar *format, /* --- variables --- */ - -static GMutex* g_messages_lock = NULL; - +static GMutex *g_messages_lock = NULL; static GLogDomain *g_log_domains = NULL; static GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK; static GPrintFunc glib_print_func = NULL; static GPrintFunc glib_printerr_func = NULL; +static GPrivate *g_log_depth = NULL; +static GLogLevelFlags g_log_msg_prefix = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_DEBUG; -static GPrivate* g_log_depth = NULL; /* --- functions --- */ #ifdef G_OS_WIN32 @@ -96,16 +95,15 @@ static GPrivate* g_log_depth = NULL; # include <windows.h> # undef STRICT # include <process.h> /* For _getpid() */ - static gboolean alloc_console_called = FALSE; - -static gboolean gonna_abort = FALSE; +static gboolean win32_keep_fatal_message = FALSE; /* This default message will usually be overwritten. */ /* Yes, a fixed size buffer is bad. So sue me. But g_error is never - * with huge strings, is it? */ -static char fatal_msg_buf[1000] = "Unspecified fatal error encountered, aborting."; -static char *fatal_msg_ptr = fatal_msg_buf; + * with huge strings, is it? + */ +static gchar fatal_msg_buf[1000] = "Unspecified fatal error encountered, aborting."; +static gchar *fatal_msg_ptr = fatal_msg_buf; /* Just use stdio. If we're out of memory, we're hosed anyway. */ #undef write @@ -114,7 +112,7 @@ dowrite (GFileDescriptor fd, const void *buf, unsigned int len) { - if (gonna_abort) + if (win32_keep_fatal_message) { memcpy (fatal_msg_ptr, buf, len); fatal_msg_ptr += len; @@ -127,7 +125,6 @@ dowrite (GFileDescriptor fd, return len; } - #define write(fd, buf, len) dowrite(fd, buf, len) static void @@ -135,7 +132,7 @@ ensure_stdout_valid (void) { HANDLE handle; - if (gonna_abort) + if (win32_keep_fatal_message) return; if (!alloc_console_called) @@ -155,115 +152,42 @@ ensure_stdout_valid (void) #endif static void -write_unsigned (GFileDescriptor fd, - gulong num, - guint radix) -{ - char buffer[64]; - gulong tmp; - char c; - int i, n; - - g_return_if_fail (radix >= 2 && radix <= 36); - - if (!num) - { - write (fd, "0", 1); - return; - } - - if (radix == 16) - write (fd, "0x", 2); - else if (radix == 8) - write (fd, "0", 1); - - n = 0; - tmp = num; - while (tmp) - { - tmp /= radix; - n++; - } - - i = n; - while (num) - { - i--; - c = (num % radix); - if (c < 10) - buffer[i] = c + '0'; - else - buffer[i] = c + 'a' - 10; - num /= radix; - } - - write (fd, buffer, n); -} - -static void write_string (GFileDescriptor fd, - gchar *string) + const gchar *string) { write (fd, string, strlen (string)); } -static GLogLevelFlags g_log_msg_prefix = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_DEBUG; - -static inline void -g_log_msg_prefix_init () +static void +g_messages_prefixed_init (void) { static gboolean initialized = FALSE; - const gchar *val; - - if (!initialized) { - - initialized = TRUE; - val = g_getenv ("G_MESSAGES_PREFIXED"); - - if (val) - { - static const GDebugKey keys[] = { - { "error", G_LOG_LEVEL_ERROR }, - { "critical", G_LOG_LEVEL_CRITICAL }, - { "warning", G_LOG_LEVEL_WARNING }, - { "message", G_LOG_LEVEL_MESSAGE }, - { "info", G_LOG_LEVEL_INFO }, - { "debug", G_LOG_LEVEL_DEBUG } - }; - - g_log_msg_prefix = g_parse_debug_string (val, keys, G_N_ELEMENTS (keys)); - } - } -} -static void -g_log_write_prefix (GFileDescriptor fd, - GLogLevelFlags mask) -{ - g_log_msg_prefix_init (); - - if ((g_log_msg_prefix & mask) == mask) + if (!initialized) { - gchar *prg_name; + const gchar *val; - prg_name = g_get_prgname (); - - if (!prg_name) - write_string (fd, "(process:"); - else + initialized = TRUE; + val = g_getenv ("G_MESSAGES_PREFIXED"); + + if (val) { - write_string (fd, prg_name); - write_string (fd, " (pid:"); + static const GDebugKey keys[] = { + { "error", G_LOG_LEVEL_ERROR }, + { "critical", G_LOG_LEVEL_CRITICAL }, + { "warning", G_LOG_LEVEL_WARNING }, + { "message", G_LOG_LEVEL_MESSAGE }, + { "info", G_LOG_LEVEL_INFO }, + { "debug", G_LOG_LEVEL_DEBUG } + }; + + g_log_msg_prefix = g_parse_debug_string (val, keys, G_N_ELEMENTS (keys)); } - - write_unsigned (fd, getpid (), 10); - write_string (fd, "): "); } } -/* HOLDS g_messages_lock */ -static inline GLogDomain* -g_log_find_domain (const gchar *log_domain) +static GLogDomain* +g_log_find_domain_L (const gchar *log_domain) { register GLogDomain *domain; @@ -277,9 +201,8 @@ g_log_find_domain (const gchar *log_domain) return NULL; } -/* HOLDS g_messages_lock */ -static inline GLogDomain* -g_log_domain_new (const gchar *log_domain) +static GLogDomain* +g_log_domain_new_L (const gchar *log_domain) { register GLogDomain *domain; @@ -294,9 +217,8 @@ g_log_domain_new (const gchar *log_domain) return domain; } -/* HOLDS g_messages_lock */ -static inline void -g_log_domain_check_free (GLogDomain *domain) +static void +g_log_domain_check_free_L (GLogDomain *domain) { if (domain->fatal_mask == G_LOG_FATAL_MASK && domain->handlers == NULL) @@ -324,11 +246,10 @@ g_log_domain_check_free (GLogDomain *domain) } } -/* HOLDS g_messages_lock */ -static inline GLogFunc -g_log_domain_get_handler (GLogDomain *domain, - GLogLevelFlags log_level, - gpointer *data) +static GLogFunc +g_log_domain_get_handler_L (GLogDomain *domain, + GLogLevelFlags log_level, + gpointer *data) { if (domain && log_level) { @@ -353,7 +274,9 @@ g_log_set_always_fatal (GLogLevelFlags fatal_mask) { GLogLevelFlags old_mask; - /* restrict the global mask to levels that are known to glib */ + /* restrict the global mask to levels that are known to glib + * since this setting applies to all domains + */ fatal_mask &= (1 << G_LOG_LEVEL_USER_SHIFT) - 1; /* force errors to be fatal */ fatal_mask |= G_LOG_LEVEL_ERROR; @@ -369,8 +292,8 @@ g_log_set_always_fatal (GLogLevelFlags fatal_mask) } GLogLevelFlags -g_log_set_fatal_mask (const gchar *log_domain, - GLogLevelFlags fatal_mask) +g_log_set_fatal_mask (const gchar *log_domain, + GLogLevelFlags fatal_mask) { GLogLevelFlags old_flags; register GLogDomain *domain; @@ -385,13 +308,13 @@ g_log_set_fatal_mask (const gchar *log_domain, g_mutex_lock (g_messages_lock); - domain = g_log_find_domain (log_domain); + domain = g_log_find_domain_L (log_domain); if (!domain) - domain = g_log_domain_new (log_domain); + domain = g_log_domain_new_L (log_domain); old_flags = domain->fatal_mask; domain->fatal_mask = fatal_mask; - g_log_domain_check_free (domain); + g_log_domain_check_free_L (domain); g_mutex_unlock (g_messages_lock); @@ -399,28 +322,29 @@ g_log_set_fatal_mask (const gchar *log_domain, } guint -g_log_set_handler (const gchar *log_domain, - GLogLevelFlags log_levels, - GLogFunc log_func, - gpointer user_data) +g_log_set_handler (const gchar *log_domain, + GLogLevelFlags log_levels, + GLogFunc log_func, + gpointer user_data) { - register GLogDomain *domain; - register GLogHandler *handler; static guint handler_id = 0; + GLogDomain *domain; + GLogHandler *handler; g_return_val_if_fail ((log_levels & G_LOG_LEVEL_MASK) != 0, 0); g_return_val_if_fail (log_func != NULL, 0); if (!log_domain) log_domain = ""; - + + handler = g_new (GLogHandler, 1); + g_mutex_lock (g_messages_lock); - domain = g_log_find_domain (log_domain); + domain = g_log_find_domain_L (log_domain); if (!domain) - domain = g_log_domain_new (log_domain); + domain = g_log_domain_new_L (log_domain); - handler = g_new (GLogHandler, 1); handler->id = ++handler_id; handler->log_level = log_levels; handler->log_func = log_func; @@ -445,11 +369,10 @@ g_log_remove_handler (const gchar *log_domain, log_domain = ""; g_mutex_lock (g_messages_lock); - - domain = g_log_find_domain (log_domain); + domain = g_log_find_domain_L (log_domain); if (domain) { - register GLogHandler *work, *last; + GLogHandler *work, *last; last = NULL; work = domain->handlers; @@ -461,21 +384,18 @@ g_log_remove_handler (const gchar *log_domain, last->next = work->next; else domain->handlers = work->next; - g_free (work); - g_log_domain_check_free (domain); - + g_log_domain_check_free_L (domain); g_mutex_unlock (g_messages_lock); + g_free (work); return; } last = work; work = last->next; } } - g_mutex_unlock (g_messages_lock); - g_warning ("g_log_remove_handler(): could not find handler with id `%d' for domain \"%s\"", - handler_id, - log_domain); + g_warning ("%s: could not find handler with id `%d' for domain \"%s\"", + G_STRLOC, handler_id, log_domain); } void @@ -485,7 +405,9 @@ g_logv (const gchar *log_domain, va_list args1) { gchar buffer[1025]; - register gint i; + gboolean was_fatal = (log_level & G_LOG_FLAG_FATAL) != 0; + gboolean was_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0; + gint i; #ifndef HAVE_VSNPRINTF va_list args2; @@ -514,9 +436,6 @@ g_logv (const gchar *log_domain, va_end (args2); #endif /* !HAVE_VSNPRINTF */ - if (!_g_debug_initialized) - _g_debug_init (); - for (i = g_bit_nth_msf (log_level, -1); i >= 0; i = g_bit_nth_msf (log_level, i)) { register GLogLevelFlags test_level; @@ -527,29 +446,53 @@ g_logv (const gchar *log_domain, guint depth = GPOINTER_TO_UINT (g_private_get (g_log_depth)); GLogDomain *domain; GLogFunc log_func; + guint domain_fatal_mask; gpointer data = NULL; - - g_mutex_lock (g_messages_lock); - domain = g_log_find_domain (log_domain ? log_domain : ""); - + if (was_fatal) + test_level |= G_LOG_FLAG_FATAL; + if (was_recursion) + test_level |= G_LOG_FLAG_RECURSION; + + /* check recursion and lookup handler */ + g_mutex_lock (g_messages_lock); + domain = g_log_find_domain_L (log_domain ? log_domain : ""); if (depth) test_level |= G_LOG_FLAG_RECURSION; - depth++; + domain_fatal_mask = domain ? domain->fatal_mask : G_LOG_FATAL_MASK; + if ((domain_fatal_mask | g_log_always_fatal) & test_level) + test_level |= G_LOG_FLAG_FATAL; + if (test_level & G_LOG_FLAG_RECURSION) + log_func = _g_log_fallback_handler; + else + log_func = g_log_domain_get_handler_L (domain, test_level, &data); + domain = NULL; + g_mutex_unlock (g_messages_lock); + g_private_set (g_log_depth, GUINT_TO_POINTER (depth)); - - if ((((domain ? domain->fatal_mask : G_LOG_FATAL_MASK) | - g_log_always_fatal) & test_level) != 0) - test_level |= G_LOG_FLAG_FATAL; - log_func = g_log_domain_get_handler (domain, test_level, &data); - g_mutex_unlock (g_messages_lock); + /* had to defer debug initialization until we can keep track of recursion */ + if (!(test_level & G_LOG_FLAG_RECURSION) && !_g_debug_initialized) + { + guint orig_test_level = test_level; + + _g_debug_init (); + if ((domain_fatal_mask | g_log_always_fatal) & test_level) + test_level |= G_LOG_FLAG_FATAL; + if (test_level != orig_test_level) + { + /* need a relookup, not nice, but not too bad either */ + g_mutex_lock (g_messages_lock); + domain = g_log_find_domain_L (log_domain ? log_domain : ""); + log_func = g_log_domain_get_handler_L (domain, test_level, &data); + domain = NULL; + g_mutex_unlock (g_messages_lock); + } + } log_func (log_domain, test_level, buffer, data); - - /* *domain can be cluttered now */ - + if (test_level & G_LOG_FLAG_FATAL) { #ifdef G_OS_WIN32 @@ -572,9 +515,9 @@ g_logv (const gchar *log_domain, } void -g_log (const gchar *log_domain, - GLogLevelFlags log_level, - const gchar *format, +g_log (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *format, ...) { va_list args; @@ -584,206 +527,262 @@ g_log (const gchar *log_domain, va_end (args); } -void -g_log_default_handler (const gchar *log_domain, - GLogLevelFlags log_level, - const gchar *message, - gpointer unused_data) +/* For a radix of 8 we need at most 3 output bytes for 1 input + * byte. Additionally we might need up to 2 output bytes for the + * readix prefix and 1 byte for the trailing NULL. + */ +#define FORMAT_UNSIGNED_BUFSIZE ((GLIB_SIZEOF_LONG * 3) + 3) + +static void +format_unsigned (gchar *buf, + gulong num, + guint radix) { - GFileDescriptor fd; - gboolean in_recursion; - gboolean is_fatal; - - in_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0; - is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0; - log_level &= G_LOG_LEVEL_MASK; - - if (!message) - message = "g_log_default_handler(): (NULL) message"; + gulong tmp; + gchar c; + gint i, n; + + /* we may not call _any_ GLib functions here (or macros like g_return_if_fail()) */ + + if (radix != 8 && radix != 10 && radix != 16) + { + *buf = '\000'; + return; + } -#ifdef G_OS_WIN32 - /* Use just stdout as stderr is hard to get redirected from the - * DOS prompt. - */ - fd = stdout; - gonna_abort = is_fatal; -#else - fd = (log_level > G_LOG_LEVEL_MESSAGE) ? 1 : 2; -#endif + if (!num) + { + *buf++ = '0'; + *buf = '\000'; + return; + } - switch (log_level) + if (radix == 16) { - case G_LOG_LEVEL_ERROR: - /* use write(2) for output, in case we are out of memeory */ - ensure_stdout_valid (); - write (fd, "\n", 1); - g_log_write_prefix (fd, log_level); + *buf++ = '0'; + *buf++ = 'x'; + } + else if (radix == 8) + { + *buf++ = '0'; + } + + n = 0; + tmp = num; + while (tmp) + { + tmp /= radix; + n++; + } - if (log_domain) - { - write (fd, log_domain, strlen (log_domain)); - write (fd, "-", 1); - } - else - write (fd, "** ", 3); - if (in_recursion) - write (fd, "ERROR (recursed) **: ", 21); - else - write (fd, "ERROR **: ", 10); - write (fd, message, strlen (message)); - if (is_fatal) - write (fd, "\naborting...\n", 13); + i = n; + + /* Again we can't use g_assert; actually this check should _never_ fail. */ + if (n > FORMAT_UNSIGNED_BUFSIZE - 3) + { + *buf = '\000'; + return; + } + + while (num) + { + i--; + c = (num % radix); + if (c < 10) + buf[i] = c + '0'; else - write (fd, "\n", 1); + buf[i] = c + 'a' - 10; + num /= radix; + } + + buf[n] = '\000'; +} + +/* string size big enough to hold level prefix */ +#define STRING_BUFFER_SIZE (FORMAT_UNSIGNED_BUFSIZE + 32) + +#define ALERT_LEVELS (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING) + +static GFileDescriptor +mklevel_prefix (gchar level_prefix[STRING_BUFFER_SIZE], + guint log_level) +{ + gboolean to_stdout = TRUE; + + /* we may not call _any_ GLib functions here */ + + switch (log_level & G_LOG_LEVEL_MASK) + { + case G_LOG_LEVEL_ERROR: + strcpy (level_prefix, "ERROR"); + to_stdout = FALSE; break; case G_LOG_LEVEL_CRITICAL: - ensure_stdout_valid (); - write (fd, "\n", 1); - g_log_write_prefix (fd, log_level); - - if (log_domain) - { - write (fd, log_domain, strlen (log_domain)); - write (fd, "-", 1); - } - else - write (fd, "** ", 3); - if (in_recursion) - write (fd, "CRITICAL (recursed) **: ", 24); - else - write (fd, "CRITICAL **: ", 13); - write (fd, message, strlen (message)); - if (is_fatal) - write (fd, "\naborting...\n", 13); - else - write (fd, "\n", 1); + strcpy (level_prefix, "CRITICAL"); + to_stdout = FALSE; break; case G_LOG_LEVEL_WARNING: - ensure_stdout_valid (); - write (fd, "\n", 1); - g_log_write_prefix (fd, log_level); - - if (log_domain) - { - write (fd, log_domain, strlen (log_domain)); - write (fd, "-", 1); - } - else - write (fd, "** ", 3); - if (in_recursion) - write (fd, "WARNING (recursed) **: ", 23); - else - write (fd, "WARNING **: ", 12); - write (fd, message, strlen (message)); - if (is_fatal) - write (fd, "\naborting...\n", 13); - else - write (fd, "\n", 1); + strcpy (level_prefix, "WARNING"); + to_stdout = FALSE; break; case G_LOG_LEVEL_MESSAGE: - ensure_stdout_valid (); - - g_log_write_prefix (fd, log_level); - - if (log_domain) - { - write (fd, log_domain, strlen (log_domain)); - write (fd, "-", 1); - } - if (in_recursion) - write (fd, "Message (recursed): ", 20); - else - write (fd, "Message: ", 9); - write (fd, message, strlen (message)); - if (is_fatal) - write (fd, "\naborting...\n", 13); - else - write (fd, "\n", 1); + strcpy (level_prefix, "Message"); + to_stdout = FALSE; break; case G_LOG_LEVEL_INFO: - ensure_stdout_valid (); - - g_log_write_prefix (fd, log_level); - - if (log_domain) + strcpy (level_prefix, "INFO"); + break; + case G_LOG_LEVEL_DEBUG: + strcpy (level_prefix, "DEBUG"); + break; + default: + if (log_level) { - write (fd, log_domain, strlen (log_domain)); - write (fd, "-", 1); + strcpy (level_prefix, "LOG-"); + format_unsigned (level_prefix + 4, log_level & G_LOG_LEVEL_MASK, 16); } - if (in_recursion) - write (fd, "INFO (recursed): ", 17); - else - write (fd, "INFO: ", 6); - write (fd, message, strlen (message)); - if (is_fatal) - write (fd, "\naborting...\n", 13); else - write (fd, "\n", 1); + strcpy (level_prefix, "LOG"); break; - case G_LOG_LEVEL_DEBUG: - ensure_stdout_valid (); + } + if (log_level & G_LOG_FLAG_RECURSION) + strcat (level_prefix, " (recursed)"); + if (log_level & ALERT_LEVELS) + strcat (level_prefix, " **"); - g_log_write_prefix (fd, log_level); + ensure_stdout_valid (); +#ifdef G_OS_WIN32 + win32_keep_fatal_message = (log_level & G_LOG_FLAG_FATAL) != 0; + /* Use just stdout as stderr is hard to get redirected from the DOS prompt. */ + return stdout; +#else + return to_stdout ? 1 : 2; +#endif +} - if (log_domain) - { - write (fd, log_domain, strlen (log_domain)); - write (fd, "-", 1); - } - if (in_recursion) - write (fd, "DEBUG (recursed): ", 18); - else - write (fd, "DEBUG: ", 7); - write (fd, message, strlen (message)); - if (is_fatal) - write (fd, "\naborting...\n", 13); +void +_g_log_fallback_handler (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer unused_data) +{ + gchar level_prefix[STRING_BUFFER_SIZE], pid_string[FORMAT_UNSIGNED_BUFSIZE]; + gboolean is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0; + GFileDescriptor fd; + + /* we can not call _any_ GLib functions in this fallback handler, + * which is why we skip UTF-8 conversion, etc. + * since we either recursed or ran out of memory, we're in a pretty + * pathologic situation anyways, what we can do is giving the + * the process ID unconditionally however. + */ + + fd = mklevel_prefix (level_prefix, log_level); + if (!message) + message = "(NULL) message"; + + format_unsigned (pid_string, getpid (), 10); + + if (log_domain) + write_string (fd, "\n"); + else + write_string (fd, "\n** "); + write_string (fd, "(process:"); + write_string (fd, pid_string); + write_string (fd, "): "); + if (log_domain) + { + write_string (fd, log_domain); + write_string (fd, "-"); + } + write_string (fd, level_prefix); + write_string (fd, ": "); + write_string (fd, message); + if (is_fatal) + write_string (fd, "\naborting...\n"); + else + write_string (fd, "\n"); +} + +void +g_log_default_handler (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer unused_data) +{ + gboolean is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0; + gchar level_prefix[STRING_BUFFER_SIZE], *string; + GString *gstring; + GFileDescriptor fd; + + /* we can be called externally with recursion for whatever reason */ + if (log_level & G_LOG_FLAG_RECURSION) + { + _g_log_fallback_handler (log_domain, log_level, message, unused_data); + return; + } + + g_messages_prefixed_init (); + + fd = mklevel_prefix (level_prefix, log_level); + + gstring = g_string_new (""); + if (log_level & ALERT_LEVELS) + g_string_append (gstring, "\n"); + if (!log_domain) + g_string_append (gstring, "** "); + + if ((g_log_msg_prefix & log_level) == log_level) + { + const gchar *prg_name = g_get_prgname (); + + if (!prg_name) + g_string_append_printf (gstring, "(process:%u): ", getpid ()); else - write (fd, "\n", 1); - break; - default: - /* we are used for a log level that is not defined by GLib itself, - * try to make the best out of it. - */ - ensure_stdout_valid (); + g_string_append_printf (gstring, "(%s:%u): ", prg_name, getpid ()); + } - g_log_write_prefix (fd, log_level); + if (log_domain) + { + g_string_append (gstring, log_domain); + g_string_append_c (gstring, '-'); + } + g_string_append (gstring, level_prefix); - if (log_domain) - { - write (fd, log_domain, strlen (log_domain)); - if (in_recursion) - write (fd, "-LOG (recursed:", 15); - else - write (fd, "-LOG (", 6); - } - else if (in_recursion) - write (fd, "LOG (recursed:", 14); + g_string_append (gstring, ": "); + if (!message) + g_string_append (gstring, "(NULL) message"); + else + { + const gchar *charset; + + if (g_get_charset (&charset)) + g_string_append (gstring, message); /* charset is UTF-8 already */ else - write (fd, "LOG (", 5); - if (log_level) { - gchar string[] = "0x00): "; - gchar *p = string + 2; - guint i; - - i = g_bit_nth_msf (log_level, -1); - *p = i >> 4; - p++; - *p = '0' + (i & 0xf); - if (*p > '9') - *p += 'A' - '9' - 1; - - write (fd, string, 7); + if (!g_utf8_validate (message, -1, NULL)) + { + g_string_append (gstring, "[Invalid UTF-8] "); + g_string_append (gstring, message); + } + else + { + string = g_convert_with_fallback (message, -1, charset, "UTF-8", + ".", NULL, NULL, NULL); + g_string_append (gstring, string); + g_free (string); + } } - else - write (fd, "): ", 3); - write (fd, message, strlen (message)); - if (is_fatal) - write (fd, "\naborting...\n", 13); - else - write (fd, "\n", 1); - break; } + if (is_fatal) + g_string_append (gstring, "\naborting...\n"); + else + g_string_append (gstring, "\n"); + + string = g_string_free (gstring, FALSE); + + write_string (fd, string); + g_free (string); } GPrintFunc @@ -816,7 +815,7 @@ g_print (const gchar *format, g_mutex_lock (g_messages_lock); local_glib_print_func = glib_print_func; g_mutex_unlock (g_messages_lock); - + if (local_glib_print_func) local_glib_print_func (string); else @@ -858,7 +857,7 @@ g_printerr (const gchar *format, g_mutex_lock (g_messages_lock); local_glib_printerr_func = glib_printerr_func; g_mutex_unlock (g_messages_lock); - + if (local_glib_printerr_func) local_glib_printerr_func (string); else @@ -891,14 +890,14 @@ printf_string_upper_bound (const gchar *format, { static const gboolean honour_longs = SIZEOF_LONG > 4 || SIZEOF_VOID_P > 4; gsize len = 1; - + if (!format) return len; - + while (*format) { register gchar c = *format++; - + if (c != '%') len += 1; else /* (c == '%') */ @@ -907,7 +906,7 @@ printf_string_upper_bound (const gchar *format, gboolean seen_l = FALSE, conv_done = FALSE; gsize conv_len = 0; const gchar *spec_start = format; - + do { c = *format++; @@ -917,7 +916,7 @@ printf_string_upper_bound (const gchar *format, guint v_uint; gint v_int; const gchar *v_string; - + /* beware of positional parameters */ case '$': @@ -927,7 +926,7 @@ printf_string_upper_bound (const gchar *format, len += 1024; /* try adding some safety padding */ conv_done = TRUE; break; - + /* parse flags */ case '#': @@ -948,7 +947,7 @@ printf_string_upper_bound (const gchar *format, case '\'': spec.locale_grouping = TRUE; break; - + /* parse output size specifications */ case '.': @@ -994,7 +993,7 @@ printf_string_upper_bound (const gchar *format, spec.min_width = MAX (spec.min_width, v_int); } break; - + /* parse type modifiers */ case 'h': @@ -1032,7 +1031,7 @@ printf_string_upper_bound (const gchar *format, spec.mod_extra_long = TRUE; #endif /* GLIB_SIZEOF_INTMAX_T > 4 */ break; - + /* parse output conversions */ case '%': @@ -1097,7 +1096,7 @@ printf_string_upper_bound (const gchar *format, u_double.mpn.biased_exponent > 0 && u_double.mpn.biased_exponent < 2047) { gint exp = u_double.mpn.biased_exponent; - + exp -= G_IEEE754_DOUBLE_BIAS; exp = exp * G_LOG_2_BASE_10 + 1; conv_len += ABS (exp); /* exp can be <0 */ @@ -1153,7 +1152,7 @@ printf_string_upper_bound (const gchar *format, v_uint = v_string ? strlen (v_string) : 0; conv_len += MAX (256, v_uint); break; - + /* handle invalid cases */ case '\000': @@ -1179,7 +1178,7 @@ printf_string_upper_bound (const gchar *format, len += conv_len; } /* else (c == '%') */ } /* while (*format) */ - + return len; } @@ -1203,29 +1202,30 @@ g_messages_init (void) { g_messages_lock = g_mutex_new (); g_log_depth = g_private_new (NULL); - g_log_msg_prefix_init (); + g_messages_prefixed_init (); _g_debug_init (); } gboolean _g_debug_initialized = FALSE; guint _g_debug_flags = 0; -void _g_debug_init () +void +_g_debug_init (void) { const gchar *val; _g_debug_initialized = TRUE; - + val = g_getenv ("G_DEBUG"); if (val != NULL) { static const GDebugKey keys[] = { {"fatal_warnings", G_DEBUG_FATAL_WARNINGS} }; - + _g_debug_flags = g_parse_debug_string (val, keys, G_N_ELEMENTS (keys)); } - + if (_g_debug_flags & G_DEBUG_FATAL_WARNINGS) { GLogLevelFlags fatal_mask; diff --git a/glib/gmessages.h b/glib/gmessages.h index 3b82b0591..b66c9c75b 100644 --- a/glib/gmessages.h +++ b/glib/gmessages.h @@ -99,6 +99,13 @@ GLogLevelFlags g_log_set_fatal_mask (const gchar *log_domain, GLogLevelFlags fatal_mask); GLogLevelFlags g_log_set_always_fatal (GLogLevelFlags fatal_mask); +/* internal */ +void _g_log_fallback_handler (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer unused_data); + + #ifndef G_LOG_DOMAIN #define G_LOG_DOMAIN ((gchar*) 0) #endif /* G_LOG_DOMAIN */ |