]>
Commit | Line | Data |
---|---|---|
b126ec4b MK |
1 | .\" Copyright (c) 2008 Linux Foundation, written by Michael Kerrisk |
2 | .\" <mtk.manpages@gmail.com> | |
3 | .\" | |
93015253 | 4 | .\" %%%LICENSE_START(VERBATIM) |
b126ec4b MK |
5 | .\" Permission is granted to make and distribute verbatim copies of this |
6 | .\" manual provided the copyright notice and this permission notice are | |
7 | .\" preserved on all copies. | |
8 | .\" | |
9 | .\" Permission is granted to copy and distribute modified versions of this | |
10 | .\" manual under the conditions for verbatim copying, provided that the | |
11 | .\" entire resulting derived work is distributed under the terms of a | |
12 | .\" permission notice identical to this one. | |
13 | .\" | |
14 | .\" Since the Linux kernel and libraries are constantly changing, this | |
15 | .\" manual page may be incorrect or out-of-date. The author(s) assume no | |
16 | .\" responsibility for errors or omissions, or for damages resulting from | |
17 | .\" the use of the information contained herein. The author(s) may not | |
18 | .\" have taken the same level of care in the production of this manual, | |
19 | .\" which is licensed free of charge, as they might when working | |
20 | .\" professionally. | |
21 | .\" | |
22 | .\" Formatted or processed versions of this manual, if unaccompanied by | |
23 | .\" the source, must acknowledge the copyright and authors of this work. | |
4b72fb64 | 24 | .\" %%%LICENSE_END |
b126ec4b | 25 | .\" |
9ba01802 | 26 | .TH PTHREAD_CLEANUP_PUSH 3 2019-03-06 "Linux" "Linux Programmer's Manual" |
b126ec4b MK |
27 | .SH NAME |
28 | pthread_cleanup_push, pthread_cleanup_pop \- push and pop | |
29 | thread cancellation clean-up handlers | |
30 | .SH SYNOPSIS | |
31 | .nf | |
32 | .B #include <pthread.h> | |
f90f031e | 33 | .PP |
b126ec4b MK |
34 | .BI "void pthread_cleanup_push(void (*" routine ")(void *)," |
35 | .BI " void *" arg ); | |
36 | .BI "void pthread_cleanup_pop(int " execute ); | |
68e4db0a | 37 | .PP |
b126ec4b | 38 | Compile and link with \fI\-pthread\fP. |
6030f2d8 | 39 | .fi |
b126ec4b MK |
40 | .SH DESCRIPTION |
41 | These functions manipulate the calling thread's stack of | |
42 | thread-cancellation clean-up handlers. | |
43 | A clean-up handler is a function that is automatically executed | |
44 | when a thread is canceled (or in various other circumstances | |
45 | described below); | |
46 | it might, for example, unlock a mutex so that | |
47 | it becomes available to other threads in the process. | |
847e0d88 | 48 | .PP |
b126ec4b MK |
49 | The |
50 | .BR pthread_cleanup_push () | |
51 | function pushes | |
52 | .I routine | |
53 | onto the top of the stack of clean-up handlers. | |
54 | When | |
55 | .I routine | |
56 | is later invoked, it will be given | |
57 | .I arg | |
58 | as its argument. | |
847e0d88 | 59 | .PP |
b126ec4b MK |
60 | The |
61 | .BR pthread_cleanup_pop () | |
62 | function removes the routine at the top of the stack of clean-up handlers, | |
63 | and optionally executes it if | |
64 | .I execute | |
c7094399 | 65 | is nonzero. |
847e0d88 | 66 | .PP |
b126ec4b MK |
67 | A cancellation clean-up handler is popped from the stack |
68 | and executed in the following circumstances: | |
69 | .IP 1. 3 | |
70 | When a thread is canceled, | |
71 | all of the stacked clean-up handlers are popped and executed in | |
72 | the reverse of the order in which they were pushed onto the stack. | |
73 | .IP 2. | |
74 | When a thread terminates by calling | |
75 | .BR pthread_exit (3), | |
76 | all clean-up handlers are executed as described in the preceding point. | |
c6fa0841 MK |
77 | (Clean-up handlers are |
78 | .I not | |
79 | called if the thread terminates by | |
b126ec4b MK |
80 | performing a |
81 | .I return | |
82 | from the thread start function.) | |
83 | .IP 3. | |
84 | When a thread calls | |
85 | .BR pthread_cleanup_pop () | |
c7094399 | 86 | with a nonzero |
b126ec4b MK |
87 | .I execute |
88 | argument, the top-most clean-up handler is popped and executed. | |
89 | .PP | |
90 | POSIX.1 permits | |
91 | .BR pthread_cleanup_push () | |
92 | and | |
93 | .BR pthread_cleanup_pop () | |
94 | to be implemented as macros that expand to text | |
95 | containing \(aq\fB{\fP\(aq and \(aq\fB}\fP\(aq, respectively. | |
96 | For this reason, the caller must ensure that calls to these | |
97 | functions are paired within the same function, | |
98 | and at the same lexical nesting level. | |
33a0ccb2 | 99 | (In other words, a clean-up handler is established only |
b126ec4b | 100 | during the execution of a specified section of code.) |
847e0d88 | 101 | .PP |
b126ec4b | 102 | Calling |
a113945f | 103 | .BR longjmp (3) |
b126ec4b MK |
104 | .RB ( siglongjmp (3)) |
105 | produces undefined results if any call has been made to | |
106 | .BR pthread_cleanup_push () | |
107 | or | |
108 | .BR pthread_cleanup_pop () | |
109 | without the matching call of the pair since the jump buffer | |
110 | was filled by | |
111 | .BR setjmp (3) | |
112 | .RB ( sigsetjmp (3)). | |
113 | Likewise, calling | |
a113945f | 114 | .BR longjmp (3) |
b126ec4b MK |
115 | .RB ( siglongjmp (3)) |
116 | from inside a clean-up handler produces undefined results | |
117 | unless the jump buffer was also filled by | |
118 | .BR setjmp (3) | |
119 | .RB ( sigsetjmp (3)) | |
120 | inside the handler. | |
121 | .SH RETURN VALUE | |
122 | These functions do not return a value. | |
123 | .SH ERRORS | |
124 | There are no errors. | |
125 | .\" SH VERSIONS | |
126 | .\" Available since glibc 2.0 | |
598445e0 ZL |
127 | .SH ATTRIBUTES |
128 | For an explanation of the terms used in this section, see | |
129 | .BR attributes (7). | |
130 | .TS | |
131 | allbox; | |
132 | lbw23 lb lb | |
133 | l l l. | |
134 | Interface Attribute Value | |
135 | T{ | |
136 | .BR pthread_cleanup_push (), | |
137 | .BR pthread_cleanup_pop () | |
138 | T} Thread safety MT-Safe | |
139 | .TE | |
847e0d88 | 140 | .sp 1 |
b126ec4b | 141 | .SH CONFORMING TO |
6cd59aeb | 142 | POSIX.1-2001, POSIX.1-2008. |
b126ec4b | 143 | .SH NOTES |
a113945f | 144 | On Linux, the |
b126ec4b MK |
145 | .BR pthread_cleanup_push () |
146 | and | |
147 | .BR pthread_cleanup_pop () | |
c6fa0841 MK |
148 | functions |
149 | .I are | |
150 | implemented as macros that expand to text | |
b126ec4b MK |
151 | containing \(aq\fB{\fP\(aq and \(aq\fB}\fP\(aq, respectively. |
152 | This means that variables declared within the scope of | |
33a0ccb2 | 153 | paired calls to these functions will be visible within only that scope. |
847e0d88 | 154 | .PP |
28e00ccf MK |
155 | POSIX.1 |
156 | .\" The text was actually added in the 2004 TC2 | |
157 | says that the effect of using | |
158 | .IR return , | |
159 | .IR break , | |
160 | .IR continue , | |
161 | or | |
162 | .IR goto | |
a113945f | 163 | to prematurely leave a block bracketed |
28e00ccf MK |
164 | .BR pthread_cleanup_push () |
165 | and | |
166 | .BR pthread_cleanup_pop () | |
167 | is undefined. | |
168 | Portable applications should avoid doing this. | |
b126ec4b MK |
169 | .SH EXAMPLE |
170 | The program below provides a simple example of the use of the functions | |
171 | described in this page. | |
172 | The program creates a thread that executes a loop bracketed by | |
173 | .BR pthread_cleanup_push () | |
174 | and | |
175 | .BR pthread_cleanup_pop (). | |
f90fec66 | 176 | This loop increments a global variable, |
b126ec4b MK |
177 | .IR cnt , |
178 | once each second. | |
179 | Depending on what command-line arguments are supplied, | |
180 | the main thread sends the other thread a cancellation request, | |
181 | or sets a global variable that causes the other thread | |
182 | to exit its loop and terminate normally (by doing a | |
183 | .IR return ). | |
847e0d88 | 184 | .PP |
b126ec4b MK |
185 | In the following shell session, |
186 | the main thread sends a cancellation request to the other thread: | |
847e0d88 | 187 | .PP |
b126ec4b | 188 | .in +4n |
b8302363 | 189 | .EX |
b126ec4b MK |
190 | $ \fB./a.out\fP |
191 | New thread started | |
192 | cnt = 0 | |
193 | cnt = 1 | |
194 | Canceling thread | |
195 | Called clean-up handler | |
196 | Thread was canceled; cnt = 0 | |
b8302363 | 197 | .EE |
b126ec4b | 198 | .in |
847e0d88 | 199 | .PP |
b126ec4b MK |
200 | From the above, we see that the thread was canceled, |
201 | and that the cancellation clean-up handler was called | |
202 | and it reset the value of the global variable | |
203 | .I cnt | |
204 | to 0. | |
847e0d88 | 205 | .PP |
b126ec4b MK |
206 | In the next run, the main program sets a |
207 | global variable that causes other thread to terminate normally: | |
847e0d88 | 208 | .PP |
b126ec4b | 209 | .in +4n |
b8302363 | 210 | .EX |
b126ec4b MK |
211 | $ \fB./a.out x\fP |
212 | New thread started | |
213 | cnt = 0 | |
214 | cnt = 1 | |
215 | Thread terminated normally; cnt = 2 | |
b8302363 | 216 | .EE |
b126ec4b | 217 | .in |
847e0d88 | 218 | .PP |
b126ec4b MK |
219 | From the above, we see that the clean-up handler was not executed (because |
220 | .I cleanup_pop_arg | |
221 | was 0), and therefore the value of | |
222 | .I cnt | |
223 | was not reset. | |
847e0d88 | 224 | .PP |
b126ec4b MK |
225 | In the next run, the main program sets a global variable that |
226 | causes the other thread to terminate normally, | |
c7094399 | 227 | and supplies a nonzero value for |
b126ec4b | 228 | .IR cleanup_pop_arg : |
847e0d88 | 229 | .PP |
b126ec4b | 230 | .in +4n |
b8302363 | 231 | .EX |
b126ec4b MK |
232 | $ \fB./a.out x 1\fP |
233 | New thread started | |
234 | cnt = 0 | |
235 | cnt = 1 | |
236 | Called clean-up handler | |
237 | Thread terminated normally; cnt = 0 | |
b8302363 | 238 | .EE |
b126ec4b | 239 | .in |
847e0d88 | 240 | .PP |
b126ec4b MK |
241 | In the above, we see that although the thread was not canceled, |
242 | the clean-up handler was executed, because the argument given to | |
243 | .BR pthread_cleanup_pop () | |
c7094399 | 244 | was nonzero. |
b126ec4b MK |
245 | .SS Program source |
246 | \& | |
e7d0bb47 | 247 | .EX |
b126ec4b MK |
248 | #include <pthread.h> |
249 | #include <sys/types.h> | |
250 | #include <stdio.h> | |
251 | #include <stdlib.h> | |
252 | #include <unistd.h> | |
253 | #include <errno.h> | |
254 | ||
d1a71985 | 255 | #define handle_error_en(en, msg) \e |
b126ec4b MK |
256 | do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) |
257 | ||
258 | static int done = 0; | |
259 | static int cleanup_pop_arg = 0; | |
260 | static int cnt = 0; | |
261 | ||
262 | static void | |
263 | cleanup_handler(void *arg) | |
264 | { | |
d1a71985 | 265 | printf("Called clean\-up handler\en"); |
b126ec4b MK |
266 | cnt = 0; |
267 | } | |
268 | ||
269 | static void * | |
270 | thread_start(void *arg) | |
271 | { | |
272 | time_t start, curr; | |
273 | ||
d1a71985 | 274 | printf("New thread started\en"); |
b126ec4b MK |
275 | |
276 | pthread_cleanup_push(cleanup_handler, NULL); | |
277 | ||
278 | curr = start = time(NULL); | |
279 | ||
280 | while (!done) { | |
281 | pthread_testcancel(); /* A cancellation point */ | |
282 | if (curr < time(NULL)) { | |
283 | curr = time(NULL); | |
d1a71985 | 284 | printf("cnt = %d\en", cnt); /* A cancellation point */ |
b126ec4b MK |
285 | cnt++; |
286 | } | |
287 | } | |
288 | ||
289 | pthread_cleanup_pop(cleanup_pop_arg); | |
290 | return NULL; | |
291 | } | |
292 | ||
293 | int | |
294 | main(int argc, char *argv[]) | |
295 | { | |
296 | pthread_t thr; | |
297 | int s; | |
298 | void *res; | |
299 | ||
0ac743c5 | 300 | s = pthread_create(&thr, NULL, thread_start, NULL); |
b126ec4b MK |
301 | if (s != 0) |
302 | handle_error_en(s, "pthread_create"); | |
303 | ||
304 | sleep(2); /* Allow new thread to run a while */ | |
305 | ||
306 | if (argc > 1) { | |
307 | if (argc > 2) | |
308 | cleanup_pop_arg = atoi(argv[2]); | |
309 | done = 1; | |
310 | ||
311 | } else { | |
d1a71985 | 312 | printf("Canceling thread\en"); |
b126ec4b MK |
313 | s = pthread_cancel(thr); |
314 | if (s != 0) | |
315 | handle_error_en(s, "pthread_cancel"); | |
316 | } | |
317 | ||
318 | s = pthread_join(thr, &res); | |
319 | if (s != 0) | |
320 | handle_error_en(s, "pthread_join"); | |
321 | ||
322 | if (res == PTHREAD_CANCELED) | |
d1a71985 | 323 | printf("Thread was canceled; cnt = %d\en", cnt); |
b126ec4b | 324 | else |
d1a71985 | 325 | printf("Thread terminated normally; cnt = %d\en", cnt); |
b126ec4b MK |
326 | exit(EXIT_SUCCESS); |
327 | } | |
e7d0bb47 | 328 | .EE |
b126ec4b MK |
329 | .SH SEE ALSO |
330 | .BR pthread_cancel (3), | |
331 | .BR pthread_cleanup_push_defer_np (3), | |
332 | .BR pthread_setcancelstate (3), | |
333 | .BR pthread_testcancel (3), | |
334 | .BR pthreads (7) |