OSDN Git Service

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