pthread_cleanup_push(3) Library Functions Manual pthread_cleanup_push(3) NOM pthread_cleanup_push, pthread_cleanup_pop -- Empiler et depiler des gestionnaires de nettoyage de threads BIBLIOTHEQUE Bibliotheque de threads POSIX (libpthread, -lpthread) SYNOPSIS #include void pthread_cleanup_push(void (*routine)(void *), void *arg); void pthread_cleanup_pop(int execute); 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'argument execute est non nul. Un gestionnaire de nettoyage est depile et execute dans les circonstances suivantes : - 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. - 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. - 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 RENVOYEE Ces fonctions ne renvoient aucune valeur. ERREURS Il n'y a pas d'erreur. ATTRIBUTS Pour une explication des termes utilises dans cette section, consulter attributes(7). +---------------------------------+--------------------------+---------+ |Interface | Attribut | Valeur | +---------------------------------+--------------------------+---------+ |pthread_cleanup_push(), | Securite des threads | MT-Safe | |pthread_cleanup_pop() | | | +---------------------------------+--------------------------+---------+ VERSIONS Sous la glibc, 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. STANDARDS POSIX.1-2008. HISTORIQUE POSIX.1-2001. glibc 2.0. EXEMPLES 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 #include #include #include #include #include #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 curr; printf("New thread started\n"); pthread_cleanup_push(cleanup_handler, NULL); curr = time(NULL); while (!done) { pthread_testcancel(); /* A cancelation point */ if (curr < time(NULL)) { curr = time(NULL); printf("cnt = %d\n", cnt); /* A cancelation 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(&thr, 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) TRADUCTION La traduction francaise de cette page de manuel a ete creee par Christophe Blaess , Stephan Rafin , Thierry Vignaud , Francois Micaux, Alain Portal , Jean-Philippe Guerard , Jean-Luc Coulon (f5ibh) , Julien Cristau , Thomas Huriaux , Nicolas Francois , Florentin Duneau , Simon Paillard , Denis Barbier , David Prevot , Frederic Hantrais et Jean- Pierre Giraud Cette traduction est une documentation libre ; veuillez vous reporter a la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITE LEGALE. Si vous decouvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message a . Pages du manuel de Linux 6.06 31 octobre 2023 pthread_cleanup_push(3)