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.
This commit is contained in:
Tim Janik 2002-03-27 17:57:30 +00:00 committed by Tim Janik
parent 564cbf8516
commit f4d7817b13
9 changed files with 480 additions and 361 deletions

View File

@ -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> Mon Mar 25 18:13:06 2002 Owen Taylor <otaylor@redhat.com>
* glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__ * glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__

View File

@ -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> Mon Mar 25 18:13:06 2002 Owen Taylor <otaylor@redhat.com>
* glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__ * glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__

View File

@ -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> Mon Mar 25 18:13:06 2002 Owen Taylor <otaylor@redhat.com>
* glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__ * glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__

View File

@ -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> Mon Mar 25 18:13:06 2002 Owen Taylor <otaylor@redhat.com>
* glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__ * glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__

View File

@ -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> Mon Mar 25 18:13:06 2002 Owen Taylor <otaylor@redhat.com>
* glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__ * glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__

View File

@ -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> Mon Mar 25 18:13:06 2002 Owen Taylor <otaylor@redhat.com>
* glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__ * glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__

View File

@ -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> Mon Mar 25 18:13:06 2002 Owen Taylor <otaylor@redhat.com>
* glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__ * glib/gtypes.h (GUINT*_SWAP_LE_BE_X86): Remove __const__

View File

@ -80,15 +80,14 @@ static gsize printf_string_upper_bound (const gchar *format,
/* --- variables --- */ /* --- variables --- */
static GMutex *g_messages_lock = NULL;
static GMutex* g_messages_lock = NULL;
static GLogDomain *g_log_domains = NULL; static GLogDomain *g_log_domains = NULL;
static GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK; static GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK;
static GPrintFunc glib_print_func = NULL; static GPrintFunc glib_print_func = NULL;
static GPrintFunc glib_printerr_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 --- */ /* --- functions --- */
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
@ -96,16 +95,15 @@ static GPrivate* g_log_depth = NULL;
# include <windows.h> # include <windows.h>
# undef STRICT # undef STRICT
# include <process.h> /* For _getpid() */ # include <process.h> /* For _getpid() */
static gboolean alloc_console_called = FALSE; static gboolean alloc_console_called = FALSE;
static gboolean win32_keep_fatal_message = FALSE;
static gboolean gonna_abort = FALSE;
/* This default message will usually be overwritten. */ /* This default message will usually be overwritten. */
/* Yes, a fixed size buffer is bad. So sue me. But g_error is never /* Yes, a fixed size buffer is bad. So sue me. But g_error is never
* with huge strings, is it? */ * with huge strings, is it?
static char fatal_msg_buf[1000] = "Unspecified fatal error encountered, aborting."; */
static char *fatal_msg_ptr = fatal_msg_buf; 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. */ /* Just use stdio. If we're out of memory, we're hosed anyway. */
#undef write #undef write
@ -114,7 +112,7 @@ dowrite (GFileDescriptor fd,
const void *buf, const void *buf,
unsigned int len) unsigned int len)
{ {
if (gonna_abort) if (win32_keep_fatal_message)
{ {
memcpy (fatal_msg_ptr, buf, len); memcpy (fatal_msg_ptr, buf, len);
fatal_msg_ptr += len; fatal_msg_ptr += len;
@ -127,7 +125,6 @@ dowrite (GFileDescriptor fd,
return len; return len;
} }
#define write(fd, buf, len) dowrite(fd, buf, len) #define write(fd, buf, len) dowrite(fd, buf, len)
static void static void
@ -135,7 +132,7 @@ ensure_stdout_valid (void)
{ {
HANDLE handle; HANDLE handle;
if (gonna_abort) if (win32_keep_fatal_message)
return; return;
if (!alloc_console_called) if (!alloc_console_called)
@ -154,68 +151,21 @@ ensure_stdout_valid (void)
#define ensure_stdout_valid() /* Define as empty */ #define ensure_stdout_valid() /* Define as empty */
#endif #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 static void
write_string (GFileDescriptor fd, write_string (GFileDescriptor fd,
gchar *string) const gchar *string)
{ {
write (fd, string, strlen (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 void
g_messages_prefixed_init (void)
static inline void
g_log_msg_prefix_init ()
{ {
static gboolean initialized = FALSE; static gboolean initialized = FALSE;
const gchar *val;
if (!initialized) { if (!initialized)
{
const gchar *val;
initialized = TRUE; initialized = TRUE;
val = g_getenv ("G_MESSAGES_PREFIXED"); val = g_getenv ("G_MESSAGES_PREFIXED");
@ -236,34 +186,8 @@ g_log_msg_prefix_init ()
} }
} }
static void static GLogDomain*
g_log_write_prefix (GFileDescriptor fd, g_log_find_domain_L (const gchar *log_domain)
GLogLevelFlags mask)
{
g_log_msg_prefix_init ();
if ((g_log_msg_prefix & mask) == mask)
{
gchar *prg_name;
prg_name = g_get_prgname ();
if (!prg_name)
write_string (fd, "(process:");
else
{
write_string (fd, prg_name);
write_string (fd, " (pid:");
}
write_unsigned (fd, getpid (), 10);
write_string (fd, "): ");
}
}
/* HOLDS g_messages_lock */
static inline GLogDomain*
g_log_find_domain (const gchar *log_domain)
{ {
register GLogDomain *domain; register GLogDomain *domain;
@ -277,9 +201,8 @@ g_log_find_domain (const gchar *log_domain)
return NULL; return NULL;
} }
/* HOLDS g_messages_lock */ static GLogDomain*
static inline GLogDomain* g_log_domain_new_L (const gchar *log_domain)
g_log_domain_new (const gchar *log_domain)
{ {
register GLogDomain *domain; register GLogDomain *domain;
@ -294,9 +217,8 @@ g_log_domain_new (const gchar *log_domain)
return domain; return domain;
} }
/* HOLDS g_messages_lock */ static void
static inline void g_log_domain_check_free_L (GLogDomain *domain)
g_log_domain_check_free (GLogDomain *domain)
{ {
if (domain->fatal_mask == G_LOG_FATAL_MASK && if (domain->fatal_mask == G_LOG_FATAL_MASK &&
domain->handlers == NULL) domain->handlers == NULL)
@ -324,9 +246,8 @@ g_log_domain_check_free (GLogDomain *domain)
} }
} }
/* HOLDS g_messages_lock */ static GLogFunc
static inline GLogFunc g_log_domain_get_handler_L (GLogDomain *domain,
g_log_domain_get_handler (GLogDomain *domain,
GLogLevelFlags log_level, GLogLevelFlags log_level,
gpointer *data) gpointer *data)
{ {
@ -353,7 +274,9 @@ g_log_set_always_fatal (GLogLevelFlags fatal_mask)
{ {
GLogLevelFlags old_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; fatal_mask &= (1 << G_LOG_LEVEL_USER_SHIFT) - 1;
/* force errors to be fatal */ /* force errors to be fatal */
fatal_mask |= G_LOG_LEVEL_ERROR; fatal_mask |= G_LOG_LEVEL_ERROR;
@ -385,13 +308,13 @@ g_log_set_fatal_mask (const gchar *log_domain,
g_mutex_lock (g_messages_lock); g_mutex_lock (g_messages_lock);
domain = g_log_find_domain (log_domain); domain = g_log_find_domain_L (log_domain);
if (!domain) if (!domain)
domain = g_log_domain_new (log_domain); domain = g_log_domain_new_L (log_domain);
old_flags = domain->fatal_mask; old_flags = domain->fatal_mask;
domain->fatal_mask = 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); g_mutex_unlock (g_messages_lock);
@ -404,9 +327,9 @@ g_log_set_handler (const gchar *log_domain,
GLogFunc log_func, GLogFunc log_func,
gpointer user_data) gpointer user_data)
{ {
register GLogDomain *domain;
register GLogHandler *handler;
static guint handler_id = 0; 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_levels & G_LOG_LEVEL_MASK) != 0, 0);
g_return_val_if_fail (log_func != NULL, 0); g_return_val_if_fail (log_func != NULL, 0);
@ -414,13 +337,14 @@ g_log_set_handler (const gchar *log_domain,
if (!log_domain) if (!log_domain)
log_domain = ""; log_domain = "";
handler = g_new (GLogHandler, 1);
g_mutex_lock (g_messages_lock); g_mutex_lock (g_messages_lock);
domain = g_log_find_domain (log_domain); domain = g_log_find_domain_L (log_domain);
if (!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->id = ++handler_id;
handler->log_level = log_levels; handler->log_level = log_levels;
handler->log_func = log_func; handler->log_func = log_func;
@ -445,11 +369,10 @@ g_log_remove_handler (const gchar *log_domain,
log_domain = ""; log_domain = "";
g_mutex_lock (g_messages_lock); g_mutex_lock (g_messages_lock);
domain = g_log_find_domain_L (log_domain);
domain = g_log_find_domain (log_domain);
if (domain) if (domain)
{ {
register GLogHandler *work, *last; GLogHandler *work, *last;
last = NULL; last = NULL;
work = domain->handlers; work = domain->handlers;
@ -461,21 +384,18 @@ g_log_remove_handler (const gchar *log_domain,
last->next = work->next; last->next = work->next;
else else
domain->handlers = work->next; domain->handlers = work->next;
g_free (work); g_log_domain_check_free_L (domain);
g_log_domain_check_free (domain);
g_mutex_unlock (g_messages_lock); g_mutex_unlock (g_messages_lock);
g_free (work);
return; return;
} }
last = work; last = work;
work = last->next; work = last->next;
} }
} }
g_mutex_unlock (g_messages_lock); g_mutex_unlock (g_messages_lock);
g_warning ("g_log_remove_handler(): could not find handler with id `%d' for domain \"%s\"", g_warning ("%s: could not find handler with id `%d' for domain \"%s\"",
handler_id, G_STRLOC, handler_id, log_domain);
log_domain);
} }
void void
@ -485,7 +405,9 @@ g_logv (const gchar *log_domain,
va_list args1) va_list args1)
{ {
gchar buffer[1025]; 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 #ifndef HAVE_VSNPRINTF
va_list args2; va_list args2;
@ -514,9 +436,6 @@ g_logv (const gchar *log_domain,
va_end (args2); va_end (args2);
#endif /* !HAVE_VSNPRINTF */ #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)) for (i = g_bit_nth_msf (log_level, -1); i >= 0; i = g_bit_nth_msf (log_level, i))
{ {
register GLogLevelFlags test_level; register GLogLevelFlags test_level;
@ -527,28 +446,52 @@ g_logv (const gchar *log_domain,
guint depth = GPOINTER_TO_UINT (g_private_get (g_log_depth)); guint depth = GPOINTER_TO_UINT (g_private_get (g_log_depth));
GLogDomain *domain; GLogDomain *domain;
GLogFunc log_func; GLogFunc log_func;
guint domain_fatal_mask;
gpointer data = NULL; gpointer data = NULL;
g_mutex_lock (g_messages_lock); if (was_fatal)
test_level |= G_LOG_FLAG_FATAL;
domain = g_log_find_domain (log_domain ? log_domain : ""); if (was_recursion)
if (depth)
test_level |= G_LOG_FLAG_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++; depth++;
g_private_set (g_log_depth, GUINT_TO_POINTER (depth)); domain_fatal_mask = domain ? domain->fatal_mask : G_LOG_FATAL_MASK;
if ((domain_fatal_mask | g_log_always_fatal) & test_level)
if ((((domain ? domain->fatal_mask : G_LOG_FATAL_MASK) |
g_log_always_fatal) & test_level) != 0)
test_level |= G_LOG_FLAG_FATAL; test_level |= G_LOG_FLAG_FATAL;
if (test_level & G_LOG_FLAG_RECURSION)
log_func = g_log_domain_get_handler (domain, test_level, &data); 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_mutex_unlock (g_messages_lock);
log_func (log_domain, test_level, buffer, data); g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
/* *domain can be cluttered now */ /* 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);
if (test_level & G_LOG_FLAG_FATAL) if (test_level & G_LOG_FLAG_FATAL)
{ {
@ -584,206 +527,262 @@ g_log (const gchar *log_domain,
va_end (args); va_end (args);
} }
/* 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)
{
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;
}
if (!num)
{
*buf++ = '0';
*buf = '\000';
return;
}
if (radix == 16)
{
*buf++ = '0';
*buf++ = 'x';
}
else if (radix == 8)
{
*buf++ = '0';
}
n = 0;
tmp = num;
while (tmp)
{
tmp /= radix;
n++;
}
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
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:
strcpy (level_prefix, "CRITICAL");
to_stdout = FALSE;
break;
case G_LOG_LEVEL_WARNING:
strcpy (level_prefix, "WARNING");
to_stdout = FALSE;
break;
case G_LOG_LEVEL_MESSAGE:
strcpy (level_prefix, "Message");
to_stdout = FALSE;
break;
case G_LOG_LEVEL_INFO:
strcpy (level_prefix, "INFO");
break;
case G_LOG_LEVEL_DEBUG:
strcpy (level_prefix, "DEBUG");
break;
default:
if (log_level)
{
strcpy (level_prefix, "LOG-");
format_unsigned (level_prefix + 4, log_level & G_LOG_LEVEL_MASK, 16);
}
else
strcpy (level_prefix, "LOG");
break;
}
if (log_level & G_LOG_FLAG_RECURSION)
strcat (level_prefix, " (recursed)");
if (log_level & ALERT_LEVELS)
strcat (level_prefix, " **");
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
}
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 void
g_log_default_handler (const gchar *log_domain, g_log_default_handler (const gchar *log_domain,
GLogLevelFlags log_level, GLogLevelFlags log_level,
const gchar *message, const gchar *message,
gpointer unused_data) gpointer unused_data)
{ {
gboolean is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
gchar level_prefix[STRING_BUFFER_SIZE], *string;
GString *gstring;
GFileDescriptor fd; GFileDescriptor fd;
gboolean in_recursion;
gboolean is_fatal;
in_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0; /* we can be called externally with recursion for whatever reason */
is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0; if (log_level & G_LOG_FLAG_RECURSION)
log_level &= G_LOG_LEVEL_MASK; {
_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
g_string_append_printf (gstring, "(%s:%u): ", prg_name, getpid ());
}
if (log_domain)
{
g_string_append (gstring, log_domain);
g_string_append_c (gstring, '-');
}
g_string_append (gstring, level_prefix);
g_string_append (gstring, ": ");
if (!message) if (!message)
message = "g_log_default_handler(): (NULL) message"; g_string_append (gstring, "(NULL) message");
else
#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
switch (log_level)
{ {
case G_LOG_LEVEL_ERROR: const gchar *charset;
/* 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);
if (log_domain) if (g_get_charset (&charset))
g_string_append (gstring, message); /* charset is UTF-8 already */
else
{ {
write (fd, log_domain, strlen (log_domain)); if (!g_utf8_validate (message, -1, NULL))
write (fd, "-", 1); {
g_string_append (gstring, "[Invalid UTF-8] ");
g_string_append (gstring, message);
} }
else else
write (fd, "** ", 3); {
if (in_recursion) string = g_convert_with_fallback (message, -1, charset, "UTF-8",
write (fd, "ERROR (recursed) **: ", 21); ".", NULL, NULL, NULL);
else g_string_append (gstring, string);
write (fd, "ERROR **: ", 10); g_free (string);
write (fd, message, strlen (message)); }
}
}
if (is_fatal) if (is_fatal)
write (fd, "\naborting...\n", 13); g_string_append (gstring, "\naborting...\n");
else else
write (fd, "\n", 1); g_string_append (gstring, "\n");
break;
case G_LOG_LEVEL_CRITICAL:
ensure_stdout_valid ();
write (fd, "\n", 1);
g_log_write_prefix (fd, log_level);
if (log_domain) string = g_string_free (gstring, FALSE);
{
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);
break;
case G_LOG_LEVEL_WARNING:
ensure_stdout_valid ();
write (fd, "\n", 1);
g_log_write_prefix (fd, log_level);
if (log_domain) write_string (fd, string);
{ g_free (string);
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);
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);
break;
case G_LOG_LEVEL_INFO:
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, "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);
break;
case G_LOG_LEVEL_DEBUG:
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, "DEBUG (recursed): ", 18);
else
write (fd, "DEBUG: ", 7);
write (fd, message, strlen (message));
if (is_fatal)
write (fd, "\naborting...\n", 13);
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_log_write_prefix (fd, log_level);
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);
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);
}
else
write (fd, "): ", 3);
write (fd, message, strlen (message));
if (is_fatal)
write (fd, "\naborting...\n", 13);
else
write (fd, "\n", 1);
break;
}
} }
GPrintFunc GPrintFunc
@ -1203,14 +1202,15 @@ g_messages_init (void)
{ {
g_messages_lock = g_mutex_new (); g_messages_lock = g_mutex_new ();
g_log_depth = g_private_new (NULL); g_log_depth = g_private_new (NULL);
g_log_msg_prefix_init (); g_messages_prefixed_init ();
_g_debug_init (); _g_debug_init ();
} }
gboolean _g_debug_initialized = FALSE; gboolean _g_debug_initialized = FALSE;
guint _g_debug_flags = 0; guint _g_debug_flags = 0;
void _g_debug_init () void
_g_debug_init (void)
{ {
const gchar *val; const gchar *val;

View File

@ -99,6 +99,13 @@ GLogLevelFlags g_log_set_fatal_mask (const gchar *log_domain,
GLogLevelFlags fatal_mask); GLogLevelFlags fatal_mask);
GLogLevelFlags g_log_set_always_fatal (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 #ifndef G_LOG_DOMAIN
#define G_LOG_DOMAIN ((gchar*) 0) #define G_LOG_DOMAIN ((gchar*) 0)
#endif /* G_LOG_DOMAIN */ #endif /* G_LOG_DOMAIN */