3 votes

Problèmes de table de hachage Glib avec le code de gestion des signaux

J'ai du code au niveau du système qui déclenche des minuteries de temps en temps, et un gestionnaire de signaux qui gère ces signaux lorsqu'ils arrivent. Cela fonctionne bien et semble tout à fait raisonnable. Il y a également deux threads distincts qui tournent en parallèle du programme principal, mais ils ne partagent aucune variable. Ils utilisent les files d'attente asynchrones de Glib pour transmettre des messages dans un seul sens.

Le même code utilise la fonction GHashTable pour stocker, eh bien, des paires clé/valeur. Lorsque le code de signal est commenté hors du système, la table de hachage semble fonctionner correctement. Cependant, lorsqu'elle est activée, il y a une étrange condition de course où l'appel à g_hash_table_lookup renvoie en fait NULL (ce qui signifie qu'il n'y a pas d'entrée avec la clé utilisée pour la recherche), alors qu'en fait l'entrée est bien là (oui, je m'en suis assuré en imprimant la liste complète des paires clé/valeur avec g_hash_table_foreach ). Pourquoi cela se produit-il la plupart du temps ? L'implémentation de la table de hachage de GLib est-elle boguée ? Parfois, l'appel à la consultation réussit.

Il s'agit d'une situation très particulière, et je peux clarifier davantage si cela n'a pas de sens, mais j'espère que je fais quelque chose de mal pour que cela puisse être corrigé.

Plus d'informations : Les segments de code qui ne sont pas dans la portée du gestionnaire de signaux mais qui accèdent à la variable g_hash_table sont entourés d'appels de blocage de signaux afin que le gestionnaire de signaux n'accède pas à ces variables alors que le processus y accédait également à l'origine.

3voto

DigitalRoss Points 80400

En général, les gestionnaires de signaux ne peuvent qu'activer des drapeaux et faire des appels système.

Il se trouve qu'il existe de sévères restrictions dans l'ISO C concernant ce que les gestionnaires de signaux peuvent faire, et que la plupart des points d'entrée des bibliothèques et la plupart des API ne sont pas, même de loin, 100% multi-thread-safe et environ 0,0% d'entre eux sont signal-handler-safe. En d'autres termes, il est absolument interdit d'appeler presque n'importe quoi à partir d'un gestionnaire de signaux.

En particulier, pour GHashTable, g_hash_table_ref() y g_hash_table_unref() sont les seuls éléments de l'API qui sont même sûrs pour les threads, et aucun d'entre eux n'est sûr pour les gestionnaires de signaux. En fait, la norme ISO-C n'autorise les gestionnaires de signaux qu'à modifier les objets déclarés avec l'option volatile sig_atomic_t et seules quelques routines de bibliothèque peuvent être appelées.

Certains d'entre nous considèrent les systèmes filetés comme intrinsèquement dangereux, des sources pratiquement radioactives de bugs subtils. Un bon endroit pour commencer à s'inquiéter est Le problème des fils. (Et notez que les gestionnaires de signaux eux-mêmes sont bien pires. Personne ne pense qu'une API est sûre à cet endroit...)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X