Provided by: manpages-fr_1.67.0-1_all bug

NOM

       pthread_cleanup_push,                              pthread_cleanup_pop,
       pthread_cleanup_push_defer_np,     pthread_cleanup_pop_restore_np     -
       Installer et enlever des gestionnaires de nettoyage.

SYNOPSIS

       #include <pthread.h>

       void pthread_cleanup_push(void (*routine) (void *), void *arg);

       void pthread_cleanup_pop(int execute);

       void   pthread_cleanup_push_defer_np(void  (*routine)  (void  *),  void
       *arg);

       void pthread_cleanup_pop_restore_np(int execute);

DESCRIPTION

       Les gestionnaires de nettoyage sont des  fonctions  qui  sont  appelées
       lorsqu’un  thread  se  termine,  soit  en appelant pthread_exit(3) soit
       parce qu’il a été annulé. Les gestionnaires de nettoyage sont installés
       et enlevés à la manière d’une pile.

       Le  rôle  d’un  gestionnaire de nettoyage est de libérer les ressources
       acquises par un thread lorsque son exécution s’achève. En  particulier,
       si  un thread se termine ou est annulé alors qu’il verrouille un mutex,
       ce dernier restera verrouillé pour toujours, empêchant d’autre  threads
       de  s’exécuter  normalement.   La meilleure manière d’empêcher cela est
       d’installer un gestionnaire de  nettoyage  dont  la  fonction  sera  de
       déverrouiller   le   mutex.  Les  gestionnaires  de  nettoyage  peuvent
       également être utilisés pour libérer des blocs de mémoire  alloués  par
       malloc(3)  ou  fermer des descripteurs de fichiers lorsque le thread se
       termine.

       pthread_cleanup_push installe la fonction routine avec  l’argument  arg
       en  tant que gestionnaire de nettoyage. A partir de ce point jusqu’à ce
       qu’un appel à la fonction pthread_cleanup_pop, la fonction routine sera
       appelée  avec  l’argument  arg  quand  le thread se terminera, soit par
       pthread_exit(3)  soit  à  la  suite  d’une  annulation.  Si   plusieurs
       gestionnaire de nettoyage ont été enregistrés, ils seront exécutés dans
       l’ordre LIFO (Last In, First Out : ordre inverse de  l’enregistrement).

       pthread_cleanup_pop  désactive  le  dernier  gestionnaire  de nettoyage
       installé. Si l’argument execute ne vaut  pas  0,  ce  gestionnaire  est
       exécuté  en  appelant  la  fonction routine avec les arguments arg.  Si
       l’argument execute vaut 0, le gestionnaire est seulement désactivé mais
       pas exécuté.

       Les  paires de pthread_cleanup_push et pthread_cleanup_pop doivent être
       exécutées dans le même bloc lexical, au même niveau et ne  peuvent  pas
       être  entrelacées  avec une autre paire.  En fait, pthread_cleanup_push
       et   pthread_cleanup_pop   sont   des   macros,   et   l’expansion   de
       pthread_cleanup_push  introduit  une  accolade  ouvrante  {  que  ferme
       l’accolade } introduite par  l’expansion  de  la  macro  correspondante
       pthread_cleanup_pop.

       pthread_cleanup_push_defer_np   est  une  extension  non  portable  qui
       combine   pthread_cleanup_push   et   pthread_setcanceltype(3).    Elle
       enregistre    le    gestionnaires    de   nettoyage   comme   le   fait
       pthread_cleanup_push, mais sauvegarde également  le  mode  d’annulation
       courant  et  le  passe  en  mode  d’annulation  retardée.  Cela  permet
       d’assurer que le mécanisme de nettoyage est efficace même si le  thread
       fonctionne en mode d’annulation asynchrone.

       pthread_cleanup_pop_restore_np   dépile   le  dernier  gestionnaire  de
       nettoyage enregistré par pthread_cleanup_push_defer_np, et restaure  le
       mode  d’annulation  à sa valeur lorsque pthread_cleanup_push_defer_np a
       été appelée.

       pthread_cleanup_push_defer_np et pthread_cleanup_pop_restore_np doivent
       être exécutée en paire, dans le même bloc, au même niveau et ne peuvent
       pas être entrelacés avec une autre paire.

       La séquence suivante

              pthread_cleanup_push_defer_np(routine, arg);
              pthread_cleanup_pop_defer_np(execute);

       est fonctionnellement équivalente (mais plus compacte et plus efficace)
       à

              { int oldtype;
                pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
                pthread_cleanup_push(routine, arg);
                ...
                pthread_cleanup_pop(execute);
                pthread_setcanceltype(oldtype, NULL);
              }

VALEUR RENVOYÉE

       Aucune.

ERREURS

       Aucune.

AUTEUR

       Xavier Leroy <Xavier.Leroy@inria.fr>

VOIR AUSSI

       pthread_exit(3), pthread_cancel(3), pthread_setcanceltype(3).

EXEMPLE

       Voici  comment  verrouiller  un  mutex  mut de telle manière qu’il sera
       déverrouillé si le thread est annulé alors que mut est verrouillé :

              pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
              pthread_mutex_lock(&mut);
              /* Faire quelque chose dutile */
              pthread_mutex_unlock(&mut);
              pthread_cleanup_pop(0);

       Les deux dernières lignes peuvent être remplacées par :

              pthread_cleanup_pop(1);

       Remarquez que le code ci-dessus n’est fiable  qu’en  mode  d’annulation
       retardée   (voir   pthread_setcanceltype(3)).    En  mode  d’annulation
       asynchrone, une annulation peut intervenir  entre  pthread_cleanup_push
       et     pthread_mutex_lock,    ou    entre    pthread_mutex_unlock    et
       pthread_cleanup_pop, résultant dans les deux cas en un  thread  tentant
       de  déverrouiller  un mutex non verrouillé par le thread courant. C’est
       la principale raison pour laquelle le mode d’annulation asynchrone  est
       si problématique à utiliser.

       Afin  que  ce code fonctionne aussi en mode d’annulation asynchrone, il
       doit  passer  en  mode  d’annulation  retardée  pour   verrouiller   et
       déverrouiller le mutex:

              pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
              pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
              pthread_mutex_lock(&mut);
              /* faire quelque chose */
              pthread_cleanup_pop(1);
              pthread_setcanceltype(oldtype, NULL);

       Le  code  ci-dessus peut être ré-écrit de manière plus compacte et plus
       efficace    en    utilisant    les     extensions     non     portables
       pthread_cleanup_push_defer_np et pthread_cleanup_pop_restore_np :

              pthread_cleanup_push_restore_np(pthread_mutex_unlock, (void *) &mut);
              pthread_mutex_lock(&mut);
              /* faire quelque chose */
              pthread_cleanup_pop_restore_np(1);

TRADUCTION

       Thierry Vignaud <tvignaud@mandrakesoft.com>, 2000
       Christophe Blaess, 2003.