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