diff options
Diffstat (limited to 'man3/pthread_cleanup_push.3')
-rw-r--r-- | man3/pthread_cleanup_push.3 | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/man3/pthread_cleanup_push.3 b/man3/pthread_cleanup_push.3 new file mode 100644 index 0000000..9fcccb3 --- /dev/null +++ b/man3/pthread_cleanup_push.3 @@ -0,0 +1,320 @@ +'\" t +.\" Copyright (c) 2008 Linux Foundation, written by Michael Kerrisk +.\" <mtk.manpages@gmail.com> +.\" +.\" SPDX-License-Identifier: Linux-man-pages-copyleft +.\" +.TH pthread_cleanup_push 3 2023-07-20 "Linux man-pages 6.05.01" +.SH NAME +pthread_cleanup_push, pthread_cleanup_pop \- push and pop +thread cancelation clean-up handlers +.SH LIBRARY +POSIX threads library +.RI ( libpthread ", " \-lpthread ) +.SH SYNOPSIS +.nf +.B #include <pthread.h> +.PP +.BI "void pthread_cleanup_push(void (*" routine ")(void *), void *" arg ); +.BI "void pthread_cleanup_pop(int " execute ); +.fi +.SH DESCRIPTION +These functions manipulate the calling thread's stack of +thread-cancelation clean-up handlers. +A clean-up handler is a function that is automatically executed +when a thread is canceled (or in various other circumstances +described below); +it might, for example, unlock a mutex so that +it becomes available to other threads in the process. +.PP +The +.BR pthread_cleanup_push () +function pushes +.I routine +onto the top of the stack of clean-up handlers. +When +.I routine +is later invoked, it will be given +.I arg +as its argument. +.PP +The +.BR pthread_cleanup_pop () +function removes the routine at the top of the stack of clean-up handlers, +and optionally executes it if +.I execute +is nonzero. +.PP +A cancelation clean-up handler is popped from the stack +and executed in the following circumstances: +.IP \[bu] 3 +When a thread is canceled, +all of the stacked clean-up handlers are popped and executed in +the reverse of the order in which they were pushed onto the stack. +.IP \[bu] +When a thread terminates by calling +.BR pthread_exit (3), +all clean-up handlers are executed as described in the preceding point. +(Clean-up handlers are +.I not +called if the thread terminates by +performing a +.I return +from the thread start function.) +.IP \[bu] +When a thread calls +.BR pthread_cleanup_pop () +with a nonzero +.I execute +argument, the top-most clean-up handler is popped and executed. +.PP +POSIX.1 permits +.BR pthread_cleanup_push () +and +.BR pthread_cleanup_pop () +to be implemented as macros that expand to text +containing \[aq]\fB{\fP\[aq] and \[aq]\fB}\fP\[aq], respectively. +For this reason, the caller must ensure that calls to these +functions are paired within the same function, +and at the same lexical nesting level. +(In other words, a clean-up handler is established only +during the execution of a specified section of code.) +.PP +Calling +.BR longjmp (3) +.RB ( siglongjmp (3)) +produces undefined results if any call has been made to +.BR pthread_cleanup_push () +or +.BR pthread_cleanup_pop () +without the matching call of the pair since the jump buffer +was filled by +.BR setjmp (3) +.RB ( sigsetjmp (3)). +Likewise, calling +.BR longjmp (3) +.RB ( siglongjmp (3)) +from inside a clean-up handler produces undefined results +unless the jump buffer was also filled by +.BR setjmp (3) +.RB ( sigsetjmp (3)) +inside the handler. +.SH RETURN VALUE +These functions do not return a value. +.SH ERRORS +There are no errors. +.SH ATTRIBUTES +For an explanation of the terms used in this section, see +.BR attributes (7). +.TS +allbox; +lbx lb lb +l l l. +Interface Attribute Value +T{ +.na +.nh +.BR pthread_cleanup_push (), +.BR pthread_cleanup_pop () +T} Thread safety MT-Safe +.TE +.sp 1 +.SH VERSIONS +On glibc, the +.BR pthread_cleanup_push () +and +.BR pthread_cleanup_pop () +functions +.I are +implemented as macros that expand to text +containing \[aq]\fB{\fP\[aq] and \[aq]\fB}\fP\[aq], respectively. +This means that variables declared within the scope of +paired calls to these functions will be visible within only that scope. +.PP +POSIX.1 +.\" The text was actually added in the 2004 TC2 +says that the effect of using +.IR return , +.IR break , +.IR continue , +or +.I goto +to prematurely leave a block bracketed +.BR pthread_cleanup_push () +and +.BR pthread_cleanup_pop () +is undefined. +Portable applications should avoid doing this. +.SH STANDARDS +POSIX.1-2008. +.SH HISTORY +POSIX.1-2001. +glibc 2.0. +.SH EXAMPLES +The program below provides a simple example of the use of the functions +described in this page. +The program creates a thread that executes a loop bracketed by +.BR pthread_cleanup_push () +and +.BR pthread_cleanup_pop (). +This loop increments a global variable, +.IR cnt , +once each second. +Depending on what command-line arguments are supplied, +the main thread sends the other thread a cancelation request, +or sets a global variable that causes the other thread +to exit its loop and terminate normally (by doing a +.IR return ). +.PP +In the following shell session, +the main thread sends a cancelation request to the other thread: +.PP +.in +4n +.EX +$ \fB./a.out\fP +New thread started +cnt = 0 +cnt = 1 +Canceling thread +Called clean\-up handler +Thread was canceled; cnt = 0 +.EE +.in +.PP +From the above, we see that the thread was canceled, +and that the cancelation clean-up handler was called +and it reset the value of the global variable +.I cnt +to 0. +.PP +In the next run, the main program sets a +global variable that causes other thread to terminate normally: +.PP +.in +4n +.EX +$ \fB./a.out x\fP +New thread started +cnt = 0 +cnt = 1 +Thread terminated normally; cnt = 2 +.EE +.in +.PP +From the above, we see that the clean-up handler was not executed (because +.I cleanup_pop_arg +was 0), and therefore the value of +.I cnt +was not reset. +.PP +In the next run, the main program sets a global variable that +causes the other thread to terminate normally, +and supplies a nonzero value for +.IR cleanup_pop_arg : +.PP +.in +4n +.EX +$ \fB./a.out x 1\fP +New thread started +cnt = 0 +cnt = 1 +Called clean\-up handler +Thread terminated normally; cnt = 0 +.EE +.in +.PP +In the above, we see that although the thread was not canceled, +the clean-up handler was executed, because the argument given to +.BR pthread_cleanup_pop () +was nonzero. +.SS Program source +\& +.\" SRC BEGIN (pthread_cleanup_push.c) +.EX +#include <errno.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <unistd.h> +\& +#define handle_error_en(en, msg) \e + 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\en"); + cnt = 0; +} +\& +static void * +thread_start(void *arg) +{ + time_t curr; +\& + printf("New thread started\en"); +\& + 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\en", 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\en"); + 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\en", cnt); + else + printf("Thread terminated normally; cnt = %d\en", cnt); + exit(EXIT_SUCCESS); +} +.EE +.\" SRC END +.SH SEE ALSO +.BR pthread_cancel (3), +.BR pthread_cleanup_push_defer_np (3), +.BR pthread_setcancelstate (3), +.BR pthread_testcancel (3), +.BR pthreads (7) |