pthread_exit () dans le gestionnaire de signaux

(Cette question est peut-être liée à pthread_exit dans le gestionnaire de signaux, ce qui cause une erreur de segmentation. ) J’écris une bibliothèque de prévention de Leadlock, où il y a toujours un thread en train de faire des graphiques et qui vérifie s’il y a un blocage, s’il en est un. fils en conflit. Lorsque ce thread attrape le signal, il libère tous les mutex qu’il possède et quitte. Il existe plusieurs mutex de ressources (évidemment) et un mutex de région critique, tous les appels à acquérir, le déblocage du verrou de ressource et les calculs de graphique doivent d’abord obtenir ce verrou. Maintenant, voilà le problème. Avec 2 threads concurrents (sans compter le thread de contrôle), il arrive que le programme se bloque après la mort d’un thread. Dans gdb, cela signifie que le thread mort a un verrou de région critique mais ne l’a jamais publié. Après avoir ajouté le point d’arrêt dans le gestionnaire de signaux et franchi le pas, il semble que le verrou appartient à quelqu’un d’autre (comme prévu) juste avant pthread_exit (), mais la propriété passe comme par magie à ce thread après pthread_exit () ..

La seule hypothèse à laquelle je puisse penser est que le thread à tuer était bloquant sur pthread_mutex_lock lorsque vous tentiez d’obtenir le verrou de région critique (car il souhaitait une autre ressource mutex), puis le signal est venu, interrompant le pthread_mutex_lock. Étant donné que cet appel n’est pas à l’abri de tout signal, il s’est passé quelque chose de bizarre? Comme si le gestionnaire de signaux était peut-être revenu et que ce thread a obtenu le verrou puis est sorti? Idk .. Toute idée est appréciée!

pthread_exit n’est pas protégé contre le signal asynchrone. Par conséquent, la seule façon de l’appeler à partir d’un gestionnaire de signaux consiste à vous assurer que le signal n’interrompt aucune fonction non sécurisée non asynchrone.

En règle générale, utiliser des signaux comme méthode de communication avec des threads est généralement une très mauvaise idée. Vous finissez par mélanger deux problèmes déjà suffisamment difficiles: la sécurité des threads (synchronisation appropriée entre les threads) et la réentrance dans un seul thread.

Si votre objective avec des signaux est simplement de demander à un thread de se terminer, un meilleur mécanisme pourrait être pthread_cancel . Cependant, pour utiliser cette fonction en toute sécurité, le thread qui sera annulé doit configurer les gestionnaires d’annulation aux points appropriés et / ou désactiver temporairement l’annulation lorsque ce n’est pas sûr (avec pthread_setcancelstate ). Sachez également que pthread_mutex_lock n’est pas un point d’annulation. Il n’existe aucun moyen sûr d’interrompre un thread bloqué dans l’attente d’obtenir un mutex. Par conséquent, si vous avez besoin de cette possibilité, vous aurez probablement besoin d’une configuration de synchronisation plus élaborée avec des variables de condition (les attentes condvar sont annulables) ou vous pouvez utiliser des sémaphores au lieu de. mutexes.

Edit: Si vous avez vraiment besoin d’un moyen de mettre fin aux threads en attente de mutex, vous pouvez remplacer les appels à pthread_mutex_lock par des appels à votre propre fonction qui effectue une boucle en appelant pthread_mutex_timedlock et en recherchant un indicateur de sortie à chaque expiration.