mount_setattr.2: Minor tweaks to Christian's patch
[man-pages.git] / man3 / pthread_cleanup_push.3
blob7960315b38c41e79e746e360a10690f1d6dd729f
1 .\" Copyright (c) 2008 Linux Foundation, written by Michael Kerrisk
2 .\"     <mtk.manpages@gmail.com>
3 .\"
4 .\" %%%LICENSE_START(VERBATIM)
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.
24 .\" %%%LICENSE_END
25 .\"
26 .TH PTHREAD_CLEANUP_PUSH 3 2021-03-22 "Linux" "Linux Programmer's Manual"
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>
33 .PP
34 .BI "void pthread_cleanup_push(void (*" routine ")(void *), void *" arg );
35 .BI "void pthread_cleanup_pop(int " execute );
36 .PP
37 Compile and link with \fI\-pthread\fP.
38 .fi
39 .SH DESCRIPTION
40 These functions manipulate the calling thread's stack of
41 thread-cancellation clean-up handlers.
42 A clean-up handler is a function that is automatically executed
43 when a thread is canceled (or in various other circumstances
44 described below);
45 it might, for example, unlock a mutex so that
46 it becomes available to other threads in the process.
47 .PP
48 The
49 .BR pthread_cleanup_push ()
50 function pushes
51 .I routine
52 onto the top of the stack of clean-up handlers.
53 When
54 .I routine
55 is later invoked, it will be given
56 .I arg
57 as its argument.
58 .PP
59 The
60 .BR pthread_cleanup_pop ()
61 function removes the routine at the top of the stack of clean-up handlers,
62 and optionally executes it if
63 .I execute
64 is nonzero.
65 .PP
66 A cancellation clean-up handler is popped from the stack
67 and executed in the following circumstances:
68 .IP 1. 3
69 When a thread is canceled,
70 all of the stacked clean-up handlers are popped and executed in
71 the reverse of the order in which they were pushed onto the stack.
72 .IP 2.
73 When a thread terminates by calling
74 .BR pthread_exit (3),
75 all clean-up handlers are executed as described in the preceding point.
76 (Clean-up handlers are
77 .I not
78 called if the thread terminates by
79 performing a
80 .I return
81 from the thread start function.)
82 .IP 3.
83 When a thread calls
84 .BR pthread_cleanup_pop ()
85 with a nonzero
86 .I execute
87 argument, the top-most clean-up handler is popped and executed.
88 .PP
89 POSIX.1 permits
90 .BR pthread_cleanup_push ()
91 and
92 .BR pthread_cleanup_pop ()
93 to be implemented as macros that expand to text
94 containing \(aq\fB{\fP\(aq and \(aq\fB}\fP\(aq, respectively.
95 For this reason, the caller must ensure that calls to these
96 functions are paired within the same function,
97 and at the same lexical nesting level.
98 (In other words, a clean-up handler is established only
99 during the execution of a specified section of code.)
101 Calling
102 .BR longjmp (3)
103 .RB ( siglongjmp (3))
104 produces undefined results if any call has been made to
105 .BR pthread_cleanup_push ()
107 .BR pthread_cleanup_pop ()
108 without the matching call of the pair since the jump buffer
109 was filled by
110 .BR setjmp (3)
111 .RB ( sigsetjmp (3)).
112 Likewise, calling
113 .BR longjmp (3)
114 .RB ( siglongjmp (3))
115 from inside a clean-up handler produces undefined results
116 unless the jump buffer was also filled by
117 .BR setjmp (3)
118 .RB ( sigsetjmp (3))
119 inside the handler.
120 .SH RETURN VALUE
121 These functions do not return a value.
122 .SH ERRORS
123 There are no errors.
124 .\" SH VERSIONS
125 .\" Available since glibc 2.0
126 .SH ATTRIBUTES
127 For an explanation of the terms used in this section, see
128 .BR attributes (7).
129 .ad l
132 allbox;
133 lbx lb lb
134 l l l.
135 Interface       Attribute       Value
137 .BR pthread_cleanup_push (),
138 .BR pthread_cleanup_pop ()
139 T}      Thread safety   MT-Safe
143 .sp 1
144 .SH CONFORMING TO
145 POSIX.1-2001, POSIX.1-2008.
146 .SH NOTES
147 On Linux, the
148 .BR pthread_cleanup_push ()
150 .BR pthread_cleanup_pop ()
151 functions
152 .I are
153 implemented as macros that expand to text
154 containing \(aq\fB{\fP\(aq and \(aq\fB}\fP\(aq, respectively.
155 This means that variables declared within the scope of
156 paired calls to these functions will be visible within only that scope.
158 POSIX.1
159 .\" The text was actually added in the 2004 TC2
160 says that the effect of using
161 .IR return ,
162 .IR break ,
163 .IR continue ,
165 .IR goto
166 to prematurely leave a block bracketed
167 .BR pthread_cleanup_push ()
169 .BR pthread_cleanup_pop ()
170 is undefined.
171 Portable applications should avoid doing this.
172 .SH EXAMPLES
173 The program below provides a simple example of the use of the functions
174 described in this page.
175 The program creates a thread that executes a loop bracketed by
176 .BR pthread_cleanup_push ()
178 .BR pthread_cleanup_pop ().
179 This loop increments a global variable,
180 .IR cnt ,
181 once each second.
182 Depending on what command-line arguments are supplied,
183 the main thread sends the other thread a cancellation request,
184 or sets a global variable that causes the other thread
185 to exit its loop and terminate normally (by doing a
186 .IR return ).
188 In the following shell session,
189 the main thread sends a cancellation request to the other thread:
191 .in +4n
193 $ \fB./a.out\fP
194 New thread started
195 cnt = 0
196 cnt = 1
197 Canceling thread
198 Called clean\-up handler
199 Thread was canceled; cnt = 0
203 From the above, we see that the thread was canceled,
204 and that the cancellation clean-up handler was called
205 and it reset the value of the global variable
206 .I cnt
207 to 0.
209 In the next run, the main program sets a
210 global variable that causes other thread to terminate normally:
212 .in +4n
214 $ \fB./a.out x\fP
215 New thread started
216 cnt = 0
217 cnt = 1
218 Thread terminated normally; cnt = 2
222 From the above, we see that the clean-up handler was not executed (because
223 .I cleanup_pop_arg
224 was 0), and therefore the value of
225 .I cnt
226 was not reset.
228 In the next run, the main program sets a global variable that
229 causes the other thread to terminate normally,
230 and supplies a nonzero value for
231 .IR cleanup_pop_arg :
233 .in +4n
235 $ \fB./a.out x 1\fP
236 New thread started
237 cnt = 0
238 cnt = 1
239 Called clean\-up handler
240 Thread terminated normally; cnt = 0
244 In the above, we see that although the thread was not canceled,
245 the clean-up handler was executed, because the argument given to
246 .BR pthread_cleanup_pop ()
247 was nonzero.
248 .SS Program source
251 #include <pthread.h>
252 #include <sys/types.h>
253 #include <stdio.h>
254 #include <stdlib.h>
255 #include <unistd.h>
256 #include <errno.h>
258 #define handle_error_en(en, msg) \e
259         do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
261 static int done = 0;
262 static int cleanup_pop_arg = 0;
263 static int cnt = 0;
265 static void
266 cleanup_handler(void *arg)
268     printf("Called clean\-up handler\en");
269     cnt = 0;
272 static void *
273 thread_start(void *arg)
275     time_t start, curr;
277     printf("New thread started\en");
279     pthread_cleanup_push(cleanup_handler, NULL);
281     curr = start = time(NULL);
283     while (!done) {
284         pthread_testcancel();           /* A cancellation point */
285         if (curr < time(NULL)) {
286             curr = time(NULL);
287             printf("cnt = %d\en", cnt);  /* A cancellation point */
288             cnt++;
289         }
290     }
292     pthread_cleanup_pop(cleanup_pop_arg);
293     return NULL;
297 main(int argc, char *argv[])
299     pthread_t thr;
300     int s;
301     void *res;
303     s = pthread_create(&thr, NULL, thread_start, NULL);
304     if (s != 0)
305         handle_error_en(s, "pthread_create");
307     sleep(2);           /* Allow new thread to run a while */
309     if (argc > 1) {
310         if (argc > 2)
311             cleanup_pop_arg = atoi(argv[2]);
312         done = 1;
314     } else {
315         printf("Canceling thread\en");
316         s = pthread_cancel(thr);
317         if (s != 0)
318             handle_error_en(s, "pthread_cancel");
319     }
321     s = pthread_join(thr, &res);
322     if (s != 0)
323         handle_error_en(s, "pthread_join");
325     if (res == PTHREAD_CANCELED)
326         printf("Thread was canceled; cnt = %d\en", cnt);
327     else
328         printf("Thread terminated normally; cnt = %d\en", cnt);
329     exit(EXIT_SUCCESS);
332 .SH SEE ALSO
333 .BR pthread_cancel (3),
334 .BR pthread_cleanup_push_defer_np (3),
335 .BR pthread_setcancelstate (3),
336 .BR pthread_testcancel (3),
337 .BR pthreads (7)