Comment puis-je tuer un pthread qui est dans une boucle infinie, de l’extérieur de cette boucle?

Je crée un fil et je le mets dans une boucle infinie. Je reçois des memory leaks lors de la vérification du code avec valgrind . Voici mon code:

#include  #include  void thread_do(void){ while(1){} } int main(){ pthread_t th; pthread_create(&th, NULL, (void *)thread_do, NULL); sleep(2); /* I want to kill thread here */ sleep(2); return 0; } 

Ainsi, un thread est créé dans main et exécute simplement thread_do () tout le temps. Y at-il un moyen de le tuer de l’intérieur principal après 2 secondes? J’ai essayé à la fois pthread_detach(th) et pthread_cancel(th) mais j’ai toujours des fuites.

    Comme @sarnold l’a souligné, par défaut, votre thread ne peut pas être annulé avec pthread_cancel() sans appeler de fonction qui constitue un point d’annulation … mais cela peut être modifié en utilisant pthread_setcanceltype() pour définir le type d’annulation du thread sur asynchrone au lieu de différé. Pour ce faire, vous appendiez quelque chose comme pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); près du début de votre fonction de fil, avant de commencer la boucle. Vous pourrez alors terminer le thread en appelant pthread_cancel(th) depuis main() .

    Notez cependant que l’annulation des threads de cette manière (qu’elle soit asynchrone ou non) ne nettoie aucune des ressources allouées dans la fonction thread (comme l’a noté Kevin dans un commentaire). Pour le faire proprement, vous pouvez:

    • Assurez-vous que le thread ne nettoie rien avant de quitter (par exemple, utiliser malloc() pour allouer un tampon)
    • Assurez-vous que vous avez un moyen de nettoyer le fil ailleurs, après sa sortie.
    • Utilisez pthread_cleanup_push() et pthread_cleanup_pop() pour append des gestionnaires de nettoyage afin de nettoyer les ressources lorsque le thread est annulé. Notez que cela présente toujours un risque si le type d’annulation est asynchrone, car le thread pourrait être annulé entre l’allocation d’une ressource et l’ajout du gestionnaire de nettoyage.
    • Évitez d’utiliser pthread_cancel() et demandez au thread de vérifier certaines conditions afin de déterminer quand se terminer (ce qui serait vérifié dans les boucles longues). Puisque votre thread vérifie lui-même la résiliation, il peut effectuer le nettoyage nécessaire après la vérification.

    Une façon d’implémenter la dernière option consiste à utiliser un mutex comme indicateur et à le tester avec pthread_mutex_trylock() encapsulé dans une fonction à utiliser dans les tests de boucle:

     #include  #include  #include  /* Returns 1 (true) if the mutex is unlocked, which is the * thread's signal to terminate. */ int needQuit(pthread_mutex_t *mtx) { switch(pthread_mutex_trylock(mtx)) { case 0: /* if we got the lock, unlock and return 1 (true) */ pthread_mutex_unlock(mtx); return 1; case EBUSY: /* return 0 (false) if the mutex was locked */ return 0; } return 1; } /* Thread function, containing a loop that's infinite except that it checks for * termination with needQuit() */ void *thread_do(void *arg) { pthread_mutex_t *mx = arg; while( !needQuit(mx) ) {} return NULL; } int main(int argc, char *argv[]) { pthread_t th; pthread_mutex_t mxq; /* mutex used as quit flag */ /* init and lock the mutex before creating the thread. As long as the mutex stays locked, the thread should keep running. A pointer to the mutex is passed as the argument to the thread function. */ pthread_mutex_init(&mxq,NULL); pthread_mutex_lock(&mxq); pthread_create(&th,NULL,thread_do,&mxq); sleep(2); /* unlock mxq to tell the thread to terminate, then join the thread */ pthread_mutex_unlock(&mxq); pthread_join(th,NULL); sleep(2); return 0; } 

    Si le thread n’est pas détaché (ce n’est généralement pas le cas par défaut), vous devez appeler pthread_join() après avoir arrêté le thread. Si le thread est détaché, vous n’avez pas besoin de le rejoindre, mais vous ne saurez pas exactement quand il se termine (ou même approximativement, à moins d’append un autre moyen d’indiquer sa sortie).

    Quelques petites pensées:

    1. Vous essayez d’annuler votre thread, mais si la politique d’annulation en vigueur concerne une annulation différée, votre thread_do() ne sera jamais annulé, car il n’appellera jamais les fonctions qui sont des points d’annulation:
      A thread's cancellation type, determined by pthread_setcanceltype(3), may be either asynchronous or deferred (the default for new threads). Asynchronous cancelability means that the thread can be canceled at any time (usually immediately, but the system does not guarantee this). Deferred cancelability means that cancellation will be delayed until the thread next calls a function that is a cancellation point. A list of functions that are or may be cancellation points is provided in pthreads(7). 
    1. Vous ne rejoignez pas le fil dans votre exemple de code simple; appelez pthread_join(3) avant la fin de votre programme:
      After a canceled thread has terminated, a join with that thread using pthread_join(3) obtains PTHREAD_CANCELED as the thread's exit status. (Joining with a thread is the only way to know that cancellation has completed.)