Provided by: manpages-fr-dev_3.27fr1.4-1_all bug

NOM

       pthread_cleanup_push,  pthread_cleanup_pop  -  Empiler  et  depiler des
       gestionnaires de nettoyage de threads

SYNOPSIS

       #include <pthread.h>

       void pthread_cleanup_push(void (*routine)(void *),
                                 void *arg);
       void pthread_cleanup_pop(int execute);

       Compilez et effectuez l'edition des liens avec l'option -pthread.

DESCRIPTION

       Ces fonctions manipulent la  pile  de  gestionnaires  de  nettoyage  du
       thread  appelant. Un gestionnaire de nettoyage est une fonction qui est
       automatiquement executee quand un thread est annule (ou  dans  d'autres
       circonstances,    decrites   ci-dessous).   Il   peut,   par   exemple,
       deverrouiller un mutex pour le rendre disponible aux autres threads  du
       processus.

       La  fonction pthread_cleanup_push() empile routine au sommet de la pile
       des  gestionnaires   de   nettoyage.   Quand   routine   sera   appelee
       ulterieurement, arg sera passe en argument.

       La  fonction  pthread_cleanup_pop()  depile  la routine au sommet de la
       pile des gestionnaires de nettoyage,  et  eventuellement  l'execute  si
       l'argumeent execute est non nul.

       Un   gestionnaire   de   nettoyage  est  depile  et  execute  dans  les
       circonstances suivantes :

       1. Quand un thread est annule,  tous  les  gestionnaires  de  nettoyage
          empiles  sont  depiles  et executes dans l'ordre inverse dans lequel
          ils ont ete empiles.

       2. Quand un thread se termine en  appelant  pthread_exit(3),  tous  les
          gestionnaires  de nettoyage sont executes comme decrit dans le point
          precedent. Il faut noter que les gestionnaires de nettoyage ne  sont
          pas appeles si le thread se termine par un return depuis la fonction
          de demarrage du thread.

       3. Quand un  thread  appelle  pthread_cleanup_pop()  avec  un  argument
          execute  non  nul, le gestionnaire de nettoyage au sommet de la pile
          est depile et execute.

       POSIX.1 autorise pthread_cleanup_push()   et  pthread_cleanup_pop()   a
       etre  implementees  comme  des  macros qui sont developpees en du texte
       contenant  << { >>  et  << } >>  respectivement.  Pour  cette   raison,
       l'appelant  doit s'assurer que les appels a ces fonctions sont apparies
       a l'interieur d'une meme fonction, et  au  meme  niveau  d'imbriquement
       lexical.  En d'autres termes, un gestionnaire de nettoyage n'est etabli
       que pendant l'execution d'une partie specifique de code.

       Un appel a longjmp(3)  (resp.  siglongjmp(3))   produit  des  resultats
       indefinis     si     un     appel    a    pthread_cleanup_push()     ou
       pthread_cleanup_pop()  a ete realise sans l'appel correspondant  de  la
       paire  si  le  tampon  de  saut  a  ete  rempli  par  setjmp(3)  (resp.
       sigsetjmp(3)). De  la  meme  maniere,  un  appel  a  longjmp(3)  (resp.
       siglongjmp(3))   depuis  un  gestionnaire  de  nettoyage  entraine  des
       resultats indefinis, sauf si le tampon de saut a lui aussi  ete  rempli
       dans setjmp(3)  (resp. sigsetjmp(3))  a l'interieur du gestionnaire.

VALEUR RENVOY'EE

       Ces fonctions ne renvoient pas de valeur.

ERREURS

       Il n'y a pas d'erreur.

CONFORMIT'E

       POSIX.1-2001.

NOTES

       Sous     Linux,     les     fonctions     pthread_cleanup_push()     et
       pthread_cleanup_pop()  sont implementees  comme  des  macros  qui  sont
       developpees  en  du  texte contenant << { >> et << } >> respectivement.
       Cela signifie que les variables declarees entre les appels  apparies  a
       ces fonctions ne seront visible qu'a l'interieur de cet intervalle.

       POSIX.1  indique  qu'utiliser  return,  break,  continue,  ou goto pour
       quitter prematurement un bloc compris entre  pthread_cleanup_push()  et
       pthread_cleanup_pop()    entraine   un   comportement   indefini.   Les
       applications portables doivent l'eviter.

EXEMPLE

       Le programme ci-dessous fournit un exemple simple de l'utilisation  des
       fonctions  decrites  dans  cette  page. Le programme cree un thread qui
       execute une boucle comprise entre des appels  a  pthread_cleanup_push()
       et pthread_cleanup_pop(). Cette boucle incremente une variable globale,
       cnt, a chaque seconde. En fonction des arguments fournis sur  la  ligne
       de  commande,,  le  thread  principal envoie une requete d'annulation a
       l'autre thread, ou definit une variable globale qui  fait  que  l'autre
       thread quitte sa boucle et se termine normalement (avec un return).

       Dans  la  session  d'interpreteur  de  commande  ci-dessous,  le thread
       principal envoie une requete d'annulation a l'autre thread :

           $ ./a.out
           New thread started
           cnt = 0
           cnt = 1
           Canceling thread
           Called clean-up handler
           Thread was canceled; cnt = 0

       Dans la sortie, nous voyons que le thread  a  ete  annule,  et  que  le
       gestionnaire  de  nettoyage  a  ete  appele  et a remis la valeur de la
       variable globale cnt a 0.

       Lors de  l'execution  suivante,  le  programme  principal  definit  une
       variable globale qui fait que l'autre thread se termine normalement :

           $ ./a.out x
           New thread started
           cnt = 0
           cnt = 1
           Thread terminated normally; cnt = 2

       Dans  la  sortie,  nous voyons que le gestionnaire de nettoyage n'a pas
       ete appele (car cleanup_pop_arg vaut 0), et la variable cnt n'a pas ete
       reinitialisee.

       Lors  de  l'execution  suivante,  le  programme  principal  definit une
       variable globale qui fait que l'autre thread se termine normalement, et
       fournit une valeur non-nulle a cleanup_pop_arg :

           $ ./a.out x 1
           New thread started
           cnt = 0
           cnt = 1
           Called clean-up handler
           Thread terminated normally; cnt = 0

       Dans  la  sortie,  nous  voyons  que  bien  que le thread n'ait pas ete
       annule, le gestionnaire de  nettoyage  a  ete  appele,  car  l'argument
       fourni a pthread_cleanup_pop n'etait pas nul.

   Source du programme

       #include <pthread.h>
       #include <sys/types.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <unistd.h>
       #include <errno.h>

       #define handle_error_en(en, msg) \
               do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

       static int done = 0;
       static int cleanup_pop_arg = 0;
       static int cnt = 0;

       static void
       cleanup_handler(void *arg)
       {
           printf("Called clean-up handler\n");
           cnt = 0;
       }

       static void *
       thread_start(void *arg)
       {
           time_t start, curr;

           printf("New thread started\n");

           pthread_cleanup_push(cleanup_handler, NULL);

           curr = start = time(NULL);

           while (!done) {
               pthread_testcancel();           /* A cancellation point */
               if (curr < time(NULL)) {
                   curr = time(NULL);
                   printf("cnt = %d\n", cnt);  /* A cancellation point */
                   cnt++;
               }
           }

           pthread_cleanup_pop(cleanup_pop_arg);
           return NULL;
       }

       int
       main(int argc, char *argv[])
       {
           pthread_t thr;
           int s;
           void *res;

           s = pthread_create(&thread, NULL, thread_start, NULL);
           if (s != 0)
               handle_error_en(s, "pthread_create");

           sleep(2);           /* Allow new thread to run a while */

           if (argc > 1) {
               if (argc > 2)
                   cleanup_pop_arg = atoi(argv[2]);
               done = 1;

           } else {
               printf("Canceling thread\n");
               s = pthread_cancel(thr);
               if (s != 0)
                   handle_error_en(s, "pthread_cancel");
           }

           s = pthread_join(thr, &res);
           if (s != 0)
               handle_error_en(s, "pthread_join");

           if (res == PTHREAD_CANCELED)
               printf("Thread was canceled; cnt = %d\n", cnt);
           else
               printf("Thread terminated normally; cnt = %d\n", cnt);
           exit(EXIT_SUCCESS);
       }

VOIR AUSSI

       pthread_cancel(3),                    pthread_cleanup_push_defer_np(3),
       pthread_setcancelstate(3), pthread_testcancel(3), pthreads(7)

COLOPHON

       Cette page fait partie de  la  publication  3.27  du  projet  man-pages
       Linux.  Une description du projet et des instructions pour signaler des
       anomalies      peuvent      etre       trouvees       a       l'adresse
       <URL:http://www.kernel.org/doc/man-pages/>.

TRADUCTION

       Depuis  2010,  cette  traduction est maintenue a l'aide de l'outil po4a
       <URL:http://po4a.alioth.debian.org/>   par   l'equipe   de   traduction
       francophone        au        sein        du       projet       perkamon
       <URL:http://perkamon.alioth.debian.org/>.

       Denis Barbier (2010).

       Veuillez  signaler  toute  erreur   de   traduction   en   ecrivant   a
       <debian-l10n-french@lists.debian.org> ou par un rapport de bogue sur le
       paquet manpages-fr.

       Vous pouvez toujours avoir acces a la version anglaise de  ce  document
       en utilisant la commande << man -L C <section> <page_de_man> >>.