1PTHREAD_CLEANUP_PUSH(3) Linux Programmer's Manual PTHREAD_CLEANUP_PUSH(3)
2
3
4
6 pthread_cleanup_push, pthread_cleanup_pop - push and pop thread cancel‐
7 lation clean-up handlers
8
10 #include <pthread.h>
11
12 void pthread_cleanup_push(void (*routine)(void *), void *arg);
13 void pthread_cleanup_pop(int execute);
14
15 Compile and link with -pthread.
16
18 These functions manipulate the calling thread's stack of thread-cancel‐
19 lation clean-up handlers. A clean-up handler is a function that is au‐
20 tomatically executed when a thread is canceled (or in various other
21 circumstances described below); it might, for example, unlock a mutex
22 so that it becomes available to other threads in the process.
23
24 The pthread_cleanup_push() function pushes routine onto the top of the
25 stack of clean-up handlers. When routine is later invoked, it will be
26 given arg as its argument.
27
28 The pthread_cleanup_pop() function removes the routine at the top of
29 the stack of clean-up handlers, and optionally executes it if execute
30 is nonzero.
31
32 A cancellation clean-up handler is popped from the stack and executed
33 in the following circumstances:
34
35 1. When a thread is canceled, all of the stacked clean-up handlers are
36 popped and executed in the reverse of the order in which they were
37 pushed onto the stack.
38
39 2. When a thread terminates by calling pthread_exit(3), all clean-up
40 handlers are executed as described in the preceding point. (Clean-
41 up handlers are not called if the thread terminates by performing a
42 return from the thread start function.)
43
44 3. When a thread calls pthread_cleanup_pop() with a nonzero execute ar‐
45 gument, the top-most clean-up handler is popped and executed.
46
47 POSIX.1 permits pthread_cleanup_push() and pthread_cleanup_pop() to be
48 implemented as macros that expand to text containing '{' and '}', re‐
49 spectively. For this reason, the caller must ensure that calls to
50 these functions are paired within the same function, and at the same
51 lexical nesting level. (In other words, a clean-up handler is estab‐
52 lished only during the execution of a specified section of code.)
53
54 Calling longjmp(3) (siglongjmp(3)) produces undefined results if any
55 call has been made to pthread_cleanup_push() or pthread_cleanup_pop()
56 without the matching call of the pair since the jump buffer was filled
57 by setjmp(3) (sigsetjmp(3)). Likewise, calling longjmp(3) (sig‐
58 longjmp(3)) from inside a clean-up handler produces undefined results
59 unless the jump buffer was also filled by setjmp(3) (sigsetjmp(3)) in‐
60 side the handler.
61
63 These functions do not return a value.
64
66 There are no errors.
67
69 For an explanation of the terms used in this section, see at‐
70 tributes(7).
71
72 ┌────────────────────────────────────────────┬───────────────┬─────────┐
73 │Interface │ Attribute │ Value │
74 ├────────────────────────────────────────────┼───────────────┼─────────┤
75 │pthread_cleanup_push(), │ Thread safety │ MT-Safe │
76 │pthread_cleanup_pop() │ │ │
77 └────────────────────────────────────────────┴───────────────┴─────────┘
78
80 POSIX.1-2001, POSIX.1-2008.
81
83 On Linux, the pthread_cleanup_push() and pthread_cleanup_pop() func‐
84 tions are implemented as macros that expand to text containing '{' and
85 '}', respectively. This means that variables declared within the scope
86 of paired calls to these functions will be visible within only that
87 scope.
88
89 POSIX.1 says that the effect of using return, break, continue, or goto
90 to prematurely leave a block bracketed pthread_cleanup_push() and
91 pthread_cleanup_pop() is undefined. Portable applications should avoid
92 doing this.
93
95 The program below provides a simple example of the use of the functions
96 described in this page. The program creates a thread that executes a
97 loop bracketed by pthread_cleanup_push() and pthread_cleanup_pop().
98 This loop increments a global variable, cnt, once each second. Depend‐
99 ing on what command-line arguments are supplied, the main thread sends
100 the other thread a cancellation request, or sets a global variable that
101 causes the other thread to exit its loop and terminate normally (by do‐
102 ing a return).
103
104 In the following shell session, the main thread sends a cancellation
105 request to the other thread:
106
107 $ ./a.out
108 New thread started
109 cnt = 0
110 cnt = 1
111 Canceling thread
112 Called clean-up handler
113 Thread was canceled; cnt = 0
114
115 From the above, we see that the thread was canceled, and that the can‐
116 cellation clean-up handler was called and it reset the value of the
117 global variable cnt to 0.
118
119 In the next run, the main program sets a global variable that causes
120 other thread to terminate normally:
121
122 $ ./a.out x
123 New thread started
124 cnt = 0
125 cnt = 1
126 Thread terminated normally; cnt = 2
127
128 From the above, we see that the clean-up handler was not executed (be‐
129 cause cleanup_pop_arg was 0), and therefore the value of cnt was not
130 reset.
131
132 In the next run, the main program sets a global variable that causes
133 the other thread to terminate normally, and supplies a nonzero value
134 for cleanup_pop_arg:
135
136 $ ./a.out x 1
137 New thread started
138 cnt = 0
139 cnt = 1
140 Called clean-up handler
141 Thread terminated normally; cnt = 0
142
143 In the above, we see that although the thread was not canceled, the
144 clean-up handler was executed, because the argument given to
145 pthread_cleanup_pop() was nonzero.
146
147 Program source
148
149 #include <pthread.h>
150 #include <sys/types.h>
151 #include <stdio.h>
152 #include <stdlib.h>
153 #include <unistd.h>
154 #include <errno.h>
155
156 #define handle_error_en(en, msg) \
157 do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
158
159 static int done = 0;
160 static int cleanup_pop_arg = 0;
161 static int cnt = 0;
162
163 static void
164 cleanup_handler(void *arg)
165 {
166 printf("Called clean-up handler\n");
167 cnt = 0;
168 }
169
170 static void *
171 thread_start(void *arg)
172 {
173 time_t start, curr;
174
175 printf("New thread started\n");
176
177 pthread_cleanup_push(cleanup_handler, NULL);
178
179 curr = start = time(NULL);
180
181 while (!done) {
182 pthread_testcancel(); /* A cancellation point */
183 if (curr < time(NULL)) {
184 curr = time(NULL);
185 printf("cnt = %d\n", cnt); /* A cancellation point */
186 cnt++;
187 }
188 }
189
190 pthread_cleanup_pop(cleanup_pop_arg);
191 return NULL;
192 }
193
194 int
195 main(int argc, char *argv[])
196 {
197 pthread_t thr;
198 int s;
199 void *res;
200
201 s = pthread_create(&thr, NULL, thread_start, NULL);
202 if (s != 0)
203 handle_error_en(s, "pthread_create");
204
205 sleep(2); /* Allow new thread to run a while */
206
207 if (argc > 1) {
208 if (argc > 2)
209 cleanup_pop_arg = atoi(argv[2]);
210 done = 1;
211
212 } else {
213 printf("Canceling thread\n");
214 s = pthread_cancel(thr);
215 if (s != 0)
216 handle_error_en(s, "pthread_cancel");
217 }
218
219 s = pthread_join(thr, &res);
220 if (s != 0)
221 handle_error_en(s, "pthread_join");
222
223 if (res == PTHREAD_CANCELED)
224 printf("Thread was canceled; cnt = %d\n", cnt);
225 else
226 printf("Thread terminated normally; cnt = %d\n", cnt);
227 exit(EXIT_SUCCESS);
228 }
229
231 pthread_cancel(3), pthread_cleanup_push_defer_np(3), pthread_setcancel‐
232 state(3), pthread_testcancel(3), pthreads(7)
233
235 This page is part of release 5.13 of the Linux man-pages project. A
236 description of the project, information about reporting bugs, and the
237 latest version of this page, can be found at
238 https://www.kernel.org/doc/man-pages/.
239
240
241
242Linux 2021-03-22 PTHREAD_CLEANUP_PUSH(3)