Friday 6 August 2004
g_log et threads
J'ai fait, par hasard, une petite découverte. GLib possède une fonctionnalité intéressante permettant de logger des messages. C'est très pratique et je vous encourage vivement à l'utiliser. Je l'utilisais dans un programme assez conséquent (en taille) et cela fonctionnait très bien, et puis tout d'un coup, j'ai commencé à avoir des bugs. Sans raison apparente. Il y avait juste un petit message qui ressemble à ceci :
(process:608): MyLogDomain-LOG-0x100 (recursed): one log message of my program aborting...
Et là, ce fut le début de la panique, qui a duré quelques heures. Après avoir regardé le code de la GLib, puis après avoir cherché sur Internet, j'ai commencé à saisir le problème. La solution est ici. Et oui, j'utilise des threads. Mais on ne m'a jamais prévenu qu'il fallait faire quelque chose de spécial...
Donc voici un petit programme pour constater ce qui se passe :
/* Compile like this to see the crash: gcc -o testlog -pthread `pkg-config --cflags --libs glib-2.0 gthread-2.0` testlog.c or like this to make it work: gcc -o testlog -DUSE_GTHREAD -pthread `pkg-config --cflags --libs glib-2.0 gthread-2.0` testlog.c */ #include <glib.h> #include <pthread.h> #define MY_LOG_DOMAIN "MyLog" #define MAX_COUNT 1000 static void log_handler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { g_print (message); } static void * count_thread (void *arg) { int max_count = GPOINTER_TO_INT (arg); int i; int pid = getpid (); for (i = 0; i < max_count; i++) { g_log (MY_LOG_DOMAIN, 1 << G_LOG_LEVEL_USER_SHIFT, "other thread (%d) - count %d\n", pid, i); } pthread_exit (NULL); } static void * count (int max_count) { int i; int pid = getpid (); for (i = 0; i < max_count; i++) { g_log (MY_LOG_DOMAIN, 1 << G_LOG_LEVEL_USER_SHIFT, "main thread (%d) - count %d\n", pid, i); } } int main (int argc, char **argv) { pthread_t thread; guint handler_id; #ifdef USE_GTHREAD g_thread_init (NULL); #endif handler_id = g_log_set_handler (MY_LOG_DOMAIN, ~0, log_handler, NULL); if (handler_id == 0) return 1; if (pthread_create (&thread, NULL, &count_thread, GINT_TO_POINTER (MAX_COUNT)) != 0) { g_log_remove_handler (MY_LOG_DOMAIN, handler_id); perror ("pthread_create"); return 1; } count (MAX_COUNT); pthread_join (thread, NULL); g_log_remove_handler (MY_LOG_DOMAIN, handler_id); return 0; }
Du coup, j'ai ouvert un petit bug.
Last Comments