my blog

Friday 6 August 2004

Petite annonce (JHDPCPCE)

Ou, en français, jeune homme donne PC pour cause emménagement. En fait, je donne un peu plus de choses que ça :

  • un 486 avec tout ce qui faut dans le boitier et qui marche. J'avais même mis une Debian dessus. C'était juste très lent.
  • un boitier qui contient une carte-mère et un processeur Cyrix 586 ou quelque chose du genre. Je ne sais même pas si un élément fonctionne...
  • un modem ADSL Sagem qui est censé fonctionner. Il n'a jamais fonctionné chez moi. Je peux même fournir deux filtres pour les prises téléphoniques.
  • éventuellement, un écran 14 pouces en bon état.
  • éventuellement, un Pentium 200 MMX en bon état avec tout ce qu'il faut dedans. C'est l'ancien 3rivieres. Il fonctionne encore, mais je ne sais pas s'il lui reste une longue vie.

Je donnerai sans problème les trois premiers produits, mais pour les deux derniers, j'aimerais bien être sûr qu'ils seront utilisés et qu'ils ne pourriront pas dans un coin. Et ce ne sera pas forcément suffisant selon mon humeur puisque j'y suis un peu attaché sentimentalement (surtout 3rivieres...).

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.

by Vincent