OSDN Git Service

LDP: Update original to LDP v3.79
[linuxjm/LDP_man-pages.git] / original / man3 / pthread_cleanup_push.3
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 2008-11-24 "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
34 .BI "void pthread_cleanup_push(void (*" routine ")(void *),"
35 .BI "                          void *" arg );
36 .BI "void pthread_cleanup_pop(int " execute );
37 .sp
38 Compile and link with \fI\-pthread\fP.
39 .fi
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.
48
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.
59
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
65 is nonzero.
66
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.
77 (Clean-up handlers are
78 .I not
79 called if the thread terminates by
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 ()
86 with a nonzero
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.
99 (In other words, a clean-up handler is established only
100 during the execution of a specified section of code.)
101
102 Calling
103 .BR longjmp (3)
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
114 .BR longjmp (3)
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
127 .SH CONFORMING TO
128 POSIX.1-2001.
129 .SH NOTES
130 On Linux, the
131 .BR pthread_cleanup_push ()
132 and
133 .BR pthread_cleanup_pop ()
134 functions
135 .I are
136 implemented as macros that expand to text
137 containing \(aq\fB{\fP\(aq and \(aq\fB}\fP\(aq, respectively.
138 This means that variables declared within the scope of
139 paired calls to these functions will be visible within only that scope.
140
141 POSIX.1
142 .\" The text was actually added in the 2004 TC2
143 says that the effect of using
144 .IR return ,
145 .IR break ,
146 .IR continue ,
147 or
148 .IR goto
149 to prematurely leave a block bracketed
150 .BR pthread_cleanup_push ()
151 and
152 .BR pthread_cleanup_pop ()
153 is undefined.
154 Portable applications should avoid doing this.
155 .SH EXAMPLE
156 The program below provides a simple example of the use of the functions
157 described in this page.
158 The program creates a thread that executes a loop bracketed by
159 .BR pthread_cleanup_push ()
160 and
161 .BR pthread_cleanup_pop ().
162 This loop increments a global variable,
163 .IR cnt ,
164 once each second.
165 Depending on what command-line arguments are supplied,
166 the main thread sends the other thread a cancellation request,
167 or sets a global variable that causes the other thread
168 to exit its loop and terminate normally (by doing a
169 .IR return ).
170
171 In the following shell session,
172 the main thread sends a cancellation request to the other thread:
173
174 .in +4n
175 .nf
176 $ \fB./a.out\fP
177 New thread started
178 cnt = 0
179 cnt = 1
180 Canceling thread
181 Called clean-up handler
182 Thread was canceled; cnt = 0
183 .fi
184 .in
185
186 From the above, we see that the thread was canceled,
187 and that the cancellation clean-up handler was called
188 and it reset the value of the global variable
189 .I cnt
190 to 0.
191
192 In the next run, the main program sets a
193 global variable that causes other thread to terminate normally:
194
195 .in +4n
196 .nf
197 $ \fB./a.out x\fP
198 New thread started
199 cnt = 0
200 cnt = 1
201 Thread terminated normally; cnt = 2
202 .fi
203 .in
204
205 From the above, we see that the clean-up handler was not executed (because
206 .I cleanup_pop_arg
207 was 0), and therefore the value of
208 .I cnt
209 was not reset.
210
211 In the next run, the main program sets a global variable that
212 causes the other thread to terminate normally,
213 and supplies a nonzero value for
214 .IR cleanup_pop_arg :
215
216 .in +4n
217 .nf
218 $ \fB./a.out x 1\fP
219 New thread started
220 cnt = 0
221 cnt = 1
222 Called clean-up handler
223 Thread terminated normally; cnt = 0
224 .fi
225 .in
226
227 In the above, we see that although the thread was not canceled,
228 the clean-up handler was executed, because the argument given to
229 .BR pthread_cleanup_pop ()
230 was nonzero.
231 .SS Program source
232 \&
233 .nf
234 #include <pthread.h>
235 #include <sys/types.h>
236 #include <stdio.h>
237 #include <stdlib.h>
238 #include <unistd.h>
239 #include <errno.h>
240
241 #define handle_error_en(en, msg) \\
242         do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
243
244 static int done = 0;
245 static int cleanup_pop_arg = 0;
246 static int cnt = 0;
247
248 static void
249 cleanup_handler(void *arg)
250 {
251     printf("Called clean\-up handler\\n");
252     cnt = 0;
253 }
254
255 static void *
256 thread_start(void *arg)
257 {
258     time_t start, curr;
259
260     printf("New thread started\\n");
261
262     pthread_cleanup_push(cleanup_handler, NULL);
263
264     curr = start = time(NULL);
265
266     while (!done) {
267         pthread_testcancel();           /* A cancellation point */
268         if (curr < time(NULL)) {
269             curr = time(NULL);
270             printf("cnt = %d\\n", cnt);  /* A cancellation point */
271             cnt++;
272         }
273     }
274
275     pthread_cleanup_pop(cleanup_pop_arg);
276     return NULL;
277 }
278
279 int
280 main(int argc, char *argv[])
281 {
282     pthread_t thr;
283     int s;
284     void *res;
285
286     s = pthread_create(&thr, NULL, thread_start, NULL);
287     if (s != 0)
288         handle_error_en(s, "pthread_create");
289
290     sleep(2);           /* Allow new thread to run a while */
291
292     if (argc > 1) {
293         if (argc > 2)
294             cleanup_pop_arg = atoi(argv[2]);
295         done = 1;
296
297     } else {
298         printf("Canceling thread\\n");
299         s = pthread_cancel(thr);
300         if (s != 0)
301             handle_error_en(s, "pthread_cancel");
302     }
303
304     s = pthread_join(thr, &res);
305     if (s != 0)
306         handle_error_en(s, "pthread_join");
307
308     if (res == PTHREAD_CANCELED)
309         printf("Thread was canceled; cnt = %d\\n", cnt);
310     else
311         printf("Thread terminated normally; cnt = %d\\n", cnt);
312     exit(EXIT_SUCCESS);
313 }
314 .fi
315 .SH SEE ALSO
316 .BR pthread_cancel (3),
317 .BR pthread_cleanup_push_defer_np (3),
318 .BR pthread_setcancelstate (3),
319 .BR pthread_testcancel (3),
320 .BR pthreads (7)
321 .SH COLOPHON
322 This page is part of release 3.79 of the Linux
323 .I man-pages
324 project.
325 A description of the project,
326 information about reporting bugs,
327 and the latest version of this page,
328 can be found at
329 \%http://www.kernel.org/doc/man\-pages/.