OSDN Git Service

(split) LDP: Update original to LDP v3.51.
[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 \fInot\fP called if the thread terminates by
78 performing a
79 .I return
80 from the thread start function.)
81 .IP 3.
82 When a thread calls
83 .BR pthread_cleanup_pop ()
84 with a nonzero
85 .I execute
86 argument, the top-most clean-up handler is popped and executed.
87 .PP
88 POSIX.1 permits
89 .BR pthread_cleanup_push ()
90 and
91 .BR pthread_cleanup_pop ()
92 to be implemented as macros that expand to text
93 containing \(aq\fB{\fP\(aq and \(aq\fB}\fP\(aq, respectively.
94 For this reason, the caller must ensure that calls to these
95 functions are paired within the same function,
96 and at the same lexical nesting level.
97 (In other words, a clean-up handler is established only
98 during the execution of a specified section of code.)
99
100 Calling
101 .BR longjmp (3)
102 .RB ( siglongjmp (3))
103 produces undefined results if any call has been made to
104 .BR pthread_cleanup_push ()
105 or
106 .BR pthread_cleanup_pop ()
107 without the matching call of the pair since the jump buffer
108 was filled by
109 .BR setjmp (3)
110 .RB ( sigsetjmp (3)).
111 Likewise, calling
112 .BR longjmp (3)
113 .RB ( siglongjmp (3))
114 from inside a clean-up handler produces undefined results
115 unless the jump buffer was also filled by
116 .BR setjmp (3)
117 .RB ( sigsetjmp (3))
118 inside the handler.
119 .SH RETURN VALUE
120 These functions do not return a value.
121 .SH ERRORS
122 There are no errors.
123 .\" SH VERSIONS
124 .\" Available since glibc 2.0
125 .SH CONFORMING TO
126 POSIX.1-2001.
127 .SH NOTES
128 On Linux, the
129 .BR pthread_cleanup_push ()
130 and
131 .BR pthread_cleanup_pop ()
132 functions \fIare\fP implemented as macros that expand to text
133 containing \(aq\fB{\fP\(aq and \(aq\fB}\fP\(aq, respectively.
134 This means that variables declared within the scope of
135 paired calls to these functions will be visible within only that scope.
136
137 POSIX.1
138 .\" The text was actually added in the 2004 TC2
139 says that the effect of using
140 .IR return ,
141 .IR break ,
142 .IR continue ,
143 or
144 .IR goto
145 to prematurely leave a block bracketed
146 .BR pthread_cleanup_push ()
147 and
148 .BR pthread_cleanup_pop ()
149 is undefined.
150 Portable applications should avoid doing this.
151 .SH EXAMPLE
152 The program below provides a simple example of the use of the functions
153 described in this page.
154 The program creates a thread that executes a loop bracketed by
155 .BR pthread_cleanup_push ()
156 and
157 .BR pthread_cleanup_pop ().
158 This loop increments a global variable,
159 .IR cnt ,
160 once each second.
161 Depending on what command-line arguments are supplied,
162 the main thread sends the other thread a cancellation request,
163 or sets a global variable that causes the other thread
164 to exit its loop and terminate normally (by doing a
165 .IR return ).
166
167 In the following shell session,
168 the main thread sends a cancellation request to the other thread:
169
170 .in +4n
171 .nf
172 $ \fB./a.out\fP
173 New thread started
174 cnt = 0
175 cnt = 1
176 Canceling thread
177 Called clean-up handler
178 Thread was canceled; cnt = 0
179 .fi
180 .in
181
182 From the above, we see that the thread was canceled,
183 and that the cancellation clean-up handler was called
184 and it reset the value of the global variable
185 .I cnt
186 to 0.
187
188 In the next run, the main program sets a
189 global variable that causes other thread to terminate normally:
190
191 .in +4n
192 .nf
193 $ \fB./a.out x\fP
194 New thread started
195 cnt = 0
196 cnt = 1
197 Thread terminated normally; cnt = 2
198 .fi
199 .in
200
201 From the above, we see that the clean-up handler was not executed (because
202 .I cleanup_pop_arg
203 was 0), and therefore the value of
204 .I cnt
205 was not reset.
206
207 In the next run, the main program sets a global variable that
208 causes the other thread to terminate normally,
209 and supplies a nonzero value for
210 .IR cleanup_pop_arg :
211
212 .in +4n
213 .nf
214 $ \fB./a.out x 1\fP
215 New thread started
216 cnt = 0
217 cnt = 1
218 Called clean-up handler
219 Thread terminated normally; cnt = 0
220 .fi
221 .in
222
223 In the above, we see that although the thread was not canceled,
224 the clean-up handler was executed, because the argument given to
225 .BR pthread_cleanup_pop ()
226 was nonzero.
227 .SS Program source
228 \&
229 .nf
230 #include <pthread.h>
231 #include <sys/types.h>
232 #include <stdio.h>
233 #include <stdlib.h>
234 #include <unistd.h>
235 #include <errno.h>
236
237 #define handle_error_en(en, msg) \\
238         do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
239
240 static int done = 0;
241 static int cleanup_pop_arg = 0;
242 static int cnt = 0;
243
244 static void
245 cleanup_handler(void *arg)
246 {
247     printf("Called clean\-up handler\\n");
248     cnt = 0;
249 }
250
251 static void *
252 thread_start(void *arg)
253 {
254     time_t start, curr;
255
256     printf("New thread started\\n");
257
258     pthread_cleanup_push(cleanup_handler, NULL);
259
260     curr = start = time(NULL);
261
262     while (!done) {
263         pthread_testcancel();           /* A cancellation point */
264         if (curr < time(NULL)) {
265             curr = time(NULL);
266             printf("cnt = %d\\n", cnt);  /* A cancellation point */
267             cnt++;
268         }
269     }
270
271     pthread_cleanup_pop(cleanup_pop_arg);
272     return NULL;
273 }
274
275 int
276 main(int argc, char *argv[])
277 {
278     pthread_t thr;
279     int s;
280     void *res;
281
282     s = pthread_create(&thr, NULL, thread_start, NULL);
283     if (s != 0)
284         handle_error_en(s, "pthread_create");
285
286     sleep(2);           /* Allow new thread to run a while */
287
288     if (argc > 1) {
289         if (argc > 2)
290             cleanup_pop_arg = atoi(argv[2]);
291         done = 1;
292
293     } else {
294         printf("Canceling thread\\n");
295         s = pthread_cancel(thr);
296         if (s != 0)
297             handle_error_en(s, "pthread_cancel");
298     }
299
300     s = pthread_join(thr, &res);
301     if (s != 0)
302         handle_error_en(s, "pthread_join");
303
304     if (res == PTHREAD_CANCELED)
305         printf("Thread was canceled; cnt = %d\\n", cnt);
306     else
307         printf("Thread terminated normally; cnt = %d\\n", cnt);
308     exit(EXIT_SUCCESS);
309 }
310 .fi
311 .SH SEE ALSO
312 .BR pthread_cancel (3),
313 .BR pthread_cleanup_push_defer_np (3),
314 .BR pthread_setcancelstate (3),
315 .BR pthread_testcancel (3),
316 .BR pthreads (7)