1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">
<TITLE>PTHREAD_CLEANUP(3) manual page</TITLE>
<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1.3 (Linux)">
<META NAME="CREATED" CONTENT="20050504;20152200">
<META NAME="CHANGED" CONTENT="20050505;18252600">
<!-- manual page source format generated by PolyglotMan v3.2, -->
<!-- available at http://polyglotman.sourceforge.net/ -->
</HEAD>
<BODY LANG="en-GB" BGCOLOR="#ffffff" DIR="LTR">
<P><A HREF="#toc">Table of Contents</A></P>
<H2><A HREF="#toc0" NAME="sect0">Name</A></H2>
<P>pthread_cleanup_push, pthread_cleanup_pop - install and remove
cleanup handlers
</P>
<H2><A HREF="#toc1" NAME="sect1">Synopsis</A></H2>
<P><B>#include <pthread.h></B>
</P>
<P><B>void pthread_cleanup_push(void (*</B><I>routine</I><B>) (void
*), void *</B><I>arg</I><B>);</B>
</P>
<P><B>void pthread_cleanup_pop(int </B><I>execute</I><B>);</B>
</P>
<H2><A HREF="#toc2" NAME="sect2">Description</A></H2>
<P>Cleanup handlers are functions that get called when a thread
terminates, either by calling <A HREF="pthread_exit.html"><B>pthread_exit</B>(3)</A>
or because of cancellation. Cleanup handlers are installed and
removed following a stack-like discipline.
</P>
<P>The purpose of cleanup handlers is to free the resources that a
thread may hold at the time it terminates. In particular, if a thread
exits or is cancelled while it owns a locked mutex, the mutex will
remain locked forever and prevent other threads from executing
normally. The best way to avoid this is, just before locking the
mutex, to install a cleanup handler whose effect is to unlock the
mutex. Cleanup handlers can be used similarly to free blocks
allocated with <A HREF="malloc.html"><B>malloc</B>(3)</A> or close
file descriptors on thread termination.
</P>
<P><B>pthread_cleanup_push</B> installs the <I>routine</I> function
with argument <I>arg</I> as a cleanup handler. From this point on to
the matching <B>pthread_cleanup_pop</B>, the function <I>routine</I>
will be called with arguments <I>arg</I> when the thread terminates,
either through <A HREF="pthread_exit.html"><B>pthread_exit</B>(3)</A>
or by cancellation. If several cleanup handlers are active at that
point, they are called in LIFO order: the most recently installed
handler is called first.
</P>
<P><B>pthread_cleanup_pop</B> removes the most recently installed
cleanup handler. If the <I>execute</I> argument is not 0, it also
executes the handler, by calling the <I>routine</I> function with
arguments <I>arg</I>. If the <I>execute</I> argument is 0, the
handler is only removed but not executed.
</P>
<P>Matching pairs of <B>pthread_cleanup_push</B> and
<B>pthread_cleanup_pop</B> must occur in the same function, at the
same level of block nesting. Actually, <B>pthread_cleanup_push</B>
and <B>pthread_cleanup_pop</B> are macros, and the expansion of
<B>pthread_cleanup_push</B> introduces an open brace <B>{</B> with
the matching closing brace <B>}</B> being introduced by the expansion
of the matching <B>pthread_cleanup_pop</B>.
</P>
<H2 STYLE="margin-top: 0cm"><A HREF="#toc3" NAME="sect3">Return Value</A></H2>
<BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm">None.
</BLOCKQUOTE>
<H2 STYLE="margin-top: 0cm"><A HREF="#toc4" NAME="sect4">Errors</A></H2>
<BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm">None.
</BLOCKQUOTE>
<H2 STYLE="margin-top: 0cm"><A HREF="#toc5" NAME="sect5">Author</A></H2>
<BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm">Xavier Leroy
<Xavier.Leroy@inria.fr>
</BLOCKQUOTE>
<BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm">Modified by
Ross Johnson for use with Pthreads-w32.</BLOCKQUOTE>
<H2 STYLE="margin-top: 0cm"><A HREF="#toc6" NAME="sect6">See Also</A></H2>
<BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm"><A HREF="pthread_exit.html"><B>pthread_exit</B>(3)</A>
, <A HREF="pthread_cancel.html"><B>pthread_cancel</B>(3)</A> ,
<A HREF="pthread_cancel.html"><B>pthread_setcanceltype</B>(3)</A> .
</BLOCKQUOTE>
<H2 STYLE="margin-top: 0cm"><A HREF="#toc7" NAME="sect7">Example</A></H2>
<BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm">Here is how
to lock a mutex <I>mut</I> in such a way that it will be unlocked if
the thread is canceled while <I>mut</I> is locked:
</BLOCKQUOTE>
<PRE>pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
pthread_mutex_lock(&mut);
/* do some work */
pthread_mutex_unlock(&mut);
pthread_cleanup_pop(0);</PRE><BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm">
Equivalently, the last two lines can be replaced by
</BLOCKQUOTE>
<PRE STYLE="margin-bottom: 0.5cm">pthread_cleanup_pop(1);</PRE><BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm">
Notice that the code above is safe only in deferred cancellation mode
(see <A HREF="pthread_cancel.html"><B>pthread_setcanceltype</B>(3)</A>
). In asynchronous cancellation mode, a cancellation can occur
between <B>pthread_cleanup_push</B> and <B>pthread_mutex_lock</B>, or
between <B>pthread_mutex_unlock</B> and <B>pthread_cleanup_pop</B>,
resulting in both cases in the thread trying to unlock a mutex not
locked by the current thread. This is the main reason why
asynchronous cancellation is difficult to use.
</BLOCKQUOTE>
<BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm">If the code
above must also work in asynchronous cancellation mode, then it must
switch to deferred mode for locking and unlocking the mutex:
</BLOCKQUOTE>
<PRE>pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);
pthread_mutex_lock(&mut);
/* do some work */
pthread_cleanup_pop(1);
pthread_setcanceltype(oldtype, NULL);</PRE>
<HR>
<BLOCKQUOTE STYLE="margin-left: 0cm; margin-right: 0cm"><A NAME="toc"></A>
<B>Table of Contents</B></BLOCKQUOTE>
<UL>
<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect0" NAME="toc0">Name</A>
</BLOCKQUOTE>
<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect1" NAME="toc1">Synopsis</A>
</BLOCKQUOTE>
<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect2" NAME="toc2">Description</A>
</BLOCKQUOTE>
<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect3" NAME="toc3">Return
Value</A>
</BLOCKQUOTE>
<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect4" NAME="toc4">Errors</A>
</BLOCKQUOTE>
<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect5" NAME="toc5">Author</A>
</BLOCKQUOTE>
<LI><BLOCKQUOTE STYLE="margin-right: 0cm; margin-bottom: 0cm"><A HREF="#sect6" NAME="toc6">See
Also</A>
</BLOCKQUOTE>
<LI><BLOCKQUOTE STYLE="margin-right: 0cm"><A HREF="#sect7" NAME="toc7">Example</A>
</BLOCKQUOTE>
</UL>
</BODY>
</HTML>
|