1pthread_cleanup_push(3)    Library Functions Manual    pthread_cleanup_push(3)
2
3
4

NAME

6       pthread_cleanup_push,  pthread_cleanup_pop - push and pop thread cance‐
7       lation clean-up handlers
8

LIBRARY

10       POSIX threads library (libpthread, -lpthread)
11

SYNOPSIS

13       #include <pthread.h>
14
15       void pthread_cleanup_push(void (*routine)(void *), void *arg);
16       void pthread_cleanup_pop(int execute);
17

DESCRIPTION

19       These functions manipulate the calling thread's stack of  thread-cance‐
20       lation clean-up handlers.  A clean-up handler is a function that is au‐
21       tomatically executed when a thread is canceled  (or  in  various  other
22       circumstances  described  below); it might, for example, unlock a mutex
23       so that it becomes available to other threads in the process.
24
25       The pthread_cleanup_push() function pushes routine onto the top of  the
26       stack  of clean-up handlers.  When routine is later invoked, it will be
27       given arg as its argument.
28
29       The pthread_cleanup_pop() function removes the routine at  the  top  of
30       the  stack  of clean-up handlers, and optionally executes it if execute
31       is nonzero.
32
33       A cancelation clean-up handler is popped from the stack and executed in
34       the following circumstances:
35
36       •  When  a thread is canceled, all of the stacked clean-up handlers are
37          popped and executed in the reverse of the order in which  they  were
38          pushed onto the stack.
39
40       •  When  a  thread  terminates by calling pthread_exit(3), all clean-up
41          handlers are executed as described in the preceding point.   (Clean-
42          up  handlers are not called if the thread terminates by performing a
43          return from the thread start function.)
44
45       •  When a thread calls pthread_cleanup_pop() with a nonzero execute ar‐
46          gument, the top-most clean-up handler is popped and executed.
47
48       POSIX.1  permits pthread_cleanup_push() and pthread_cleanup_pop() to be
49       implemented as macros that expand to text containing '{' and  '}',  re‐
50       spectively.   For  this  reason,  the  caller must ensure that calls to
51       these functions are paired within the same function, and  at  the  same
52       lexical  nesting  level.  (In other words, a clean-up handler is estab‐
53       lished only during the execution of a specified section of code.)
54
55       Calling longjmp(3) (siglongjmp(3)) produces undefined  results  if  any
56       call  has  been made to pthread_cleanup_push() or pthread_cleanup_pop()
57       without the matching call of the pair since the jump buffer was  filled
58       by   setjmp(3)  (sigsetjmp(3)).   Likewise,  calling  longjmp(3)  (sig‐
59       longjmp(3)) from inside a clean-up handler produces  undefined  results
60       unless  the jump buffer was also filled by setjmp(3) (sigsetjmp(3)) in‐
61       side the handler.
62

RETURN VALUE

64       These functions do not return a value.
65

ERRORS

67       There are no errors.
68

ATTRIBUTES

70       For an  explanation  of  the  terms  used  in  this  section,  see  at‐
71       tributes(7).
72
73       ┌────────────────────────────────────────────┬───────────────┬─────────┐
74Interface                                   Attribute     Value   
75       ├────────────────────────────────────────────┼───────────────┼─────────┤
76pthread_cleanup_push(),                     │ Thread safety │ MT-Safe │
77pthread_cleanup_pop()                       │               │         │
78       └────────────────────────────────────────────┴───────────────┴─────────┘
79

VERSIONS

81       On glibc, the pthread_cleanup_push()  and  pthread_cleanup_pop()  func‐
82       tions  are implemented as macros that expand to text containing '{' and
83       '}', respectively.  This means that variables declared within the scope
84       of  paired  calls  to  these functions will be visible within only that
85       scope.
86
87       POSIX.1 says that the effect of using return, break, continue, or  goto
88       to  prematurely  leave  a  block  bracketed  pthread_cleanup_push() and
89       pthread_cleanup_pop() is undefined.  Portable applications should avoid
90       doing this.
91

STANDARDS

93       POSIX.1-2008.
94

HISTORY

96       POSIX.1-2001.  glibc 2.0.
97

EXAMPLES

99       The program below provides a simple example of the use of the functions
100       described in this page.  The program creates a thread that  executes  a
101       loop  bracketed  by  pthread_cleanup_push()  and pthread_cleanup_pop().
102       This loop increments a global variable, cnt, once each second.  Depend‐
103       ing  on what command-line arguments are supplied, the main thread sends
104       the other thread a cancelation request, or sets a global variable  that
105       causes the other thread to exit its loop and terminate normally (by do‐
106       ing a return).
107
108       In the following shell session, the main thread sends a cancelation re‐
109       quest to the other thread:
110
111           $ ./a.out
112           New thread started
113           cnt = 0
114           cnt = 1
115           Canceling thread
116           Called clean-up handler
117           Thread was canceled; cnt = 0
118
119       From  the above, we see that the thread was canceled, and that the can‐
120       celation clean-up handler was called and it  reset  the  value  of  the
121       global variable cnt to 0.
122
123       In  the  next  run, the main program sets a global variable that causes
124       other thread to terminate normally:
125
126           $ ./a.out x
127           New thread started
128           cnt = 0
129           cnt = 1
130           Thread terminated normally; cnt = 2
131
132       From the above, we see that the clean-up handler was not executed  (be‐
133       cause  cleanup_pop_arg  was  0), and therefore the value of cnt was not
134       reset.
135
136       In the next run, the main program sets a global  variable  that  causes
137       the  other  thread  to terminate normally, and supplies a nonzero value
138       for cleanup_pop_arg:
139
140           $ ./a.out x 1
141           New thread started
142           cnt = 0
143           cnt = 1
144           Called clean-up handler
145           Thread terminated normally; cnt = 0
146
147       In the above, we see that although the thread  was  not  canceled,  the
148       clean-up   handler   was   executed,  because  the  argument  given  to
149       pthread_cleanup_pop() was nonzero.
150
151   Program source
152
153       #include <errno.h>
154       #include <pthread.h>
155       #include <stdio.h>
156       #include <stdlib.h>
157       #include <sys/types.h>
158       #include <unistd.h>
159
160       #define handle_error_en(en, msg) \
161               do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
162
163       static int done = 0;
164       static int cleanup_pop_arg = 0;
165       static int cnt = 0;
166
167       static void
168       cleanup_handler(void *arg)
169       {
170           printf("Called clean-up handler\n");
171           cnt = 0;
172       }
173
174       static void *
175       thread_start(void *arg)
176       {
177           time_t curr;
178
179           printf("New thread started\n");
180
181           pthread_cleanup_push(cleanup_handler, NULL);
182
183           curr = time(NULL);
184
185           while (!done) {
186               pthread_testcancel();           /* A cancelation point */
187               if (curr < time(NULL)) {
188                   curr = time(NULL);
189                   printf("cnt = %d\n", cnt);  /* A cancelation point */
190                   cnt++;
191               }
192           }
193
194           pthread_cleanup_pop(cleanup_pop_arg);
195           return NULL;
196       }
197
198       int
199       main(int argc, char *argv[])
200       {
201           pthread_t thr;
202           int s;
203           void *res;
204
205           s = pthread_create(&thr, NULL, thread_start, NULL);
206           if (s != 0)
207               handle_error_en(s, "pthread_create");
208
209           sleep(2);           /* Allow new thread to run a while */
210
211           if (argc > 1) {
212               if (argc > 2)
213                   cleanup_pop_arg = atoi(argv[2]);
214               done = 1;
215
216           } else {
217               printf("Canceling thread\n");
218               s = pthread_cancel(thr);
219               if (s != 0)
220                   handle_error_en(s, "pthread_cancel");
221           }
222
223           s = pthread_join(thr, &res);
224           if (s != 0)
225               handle_error_en(s, "pthread_join");
226
227           if (res == PTHREAD_CANCELED)
228               printf("Thread was canceled; cnt = %d\n", cnt);
229           else
230               printf("Thread terminated normally; cnt = %d\n", cnt);
231           exit(EXIT_SUCCESS);
232       }
233

SEE ALSO

235       pthread_cancel(3), pthread_cleanup_push_defer_np(3), pthread_setcancel‐
236       state(3), pthread_testcancel(3), pthreads(7)
237
238
239
240Linux man-pages 6.04              2023-03-30           pthread_cleanup_push(3)
Impressum