Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / devtools / amd64 / html / python / ext / thinIce.html
CommitLineData
920dae64
AT
1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
2<html>
3<head>
4<link rel="STYLESHEET" href="ext.css" type='text/css' />
5<link rel="SHORTCUT ICON" href="../icons/pyfav.png" type="image/png" />
6<link rel='start' href='../index.html' title='Python Documentation Index' />
7<link rel="first" href="ext.html" title='Extending and Embedding the Python Interpreter' />
8<link rel='contents' href='contents.html' title="Contents" />
9<link rel='last' href='about.html' title='About this document...' />
10<link rel='help' href='about.html' title='About this document...' />
11<link rel="next" href="nullPointers.html" />
12<link rel="prev" href="ownershipRules.html" />
13<link rel="parent" href="refcounts.html" />
14<link rel="next" href="nullPointers.html" />
15<meta name='aesop' content='information' />
16<title>1.10.3 Thin Ice
17</title>
18</head>
19<body>
20<DIV CLASS="navigation">
21<div id='top-navigation-panel' xml:id='top-navigation-panel'>
22<table align="center" width="100%" cellpadding="0" cellspacing="2">
23<tr>
24<td class='online-navigation'><a rel="prev" title="1.10.2 Ownership Rules"
25 href="ownershipRules.html"><img src='../icons/previous.png'
26 border='0' height='32' alt='Previous Page' width='32' /></A></td>
27<td class='online-navigation'><a rel="parent" title="1.10 Reference Counts"
28 href="refcounts.html"><img src='../icons/up.png'
29 border='0' height='32' alt='Up One Level' width='32' /></A></td>
30<td class='online-navigation'><a rel="next" title="1.10.4 NULL Pointers"
31 href="nullPointers.html"><img src='../icons/next.png'
32 border='0' height='32' alt='Next Page' width='32' /></A></td>
33<td align="center" width="100%">Extending and Embedding the Python Interpreter</td>
34<td class='online-navigation'><a rel="contents" title="Table of Contents"
35 href="contents.html"><img src='../icons/contents.png'
36 border='0' height='32' alt='Contents' width='32' /></A></td>
37<td class='online-navigation'><img src='../icons/blank.png'
38 border='0' height='32' alt='' width='32' /></td>
39<td class='online-navigation'><img src='../icons/blank.png'
40 border='0' height='32' alt='' width='32' /></td>
41</tr></table>
42<div class='online-navigation'>
43<b class="navlabel">Previous:</b>
44<a class="sectref" rel="prev" href="ownershipRules.html">1.10.2 Ownership Rules</A>
45<b class="navlabel">Up:</b>
46<a class="sectref" rel="parent" href="refcounts.html">1.10 Reference Counts</A>
47<b class="navlabel">Next:</b>
48<a class="sectref" rel="next" href="nullPointers.html">1.10.4 NULL Pointers</A>
49</div>
50<hr /></div>
51</DIV>
52<!--End of Navigation Panel-->
53
54<H2><A NAME="SECTION0031030000000000000000"></A><A NAME="thinIce"></A>
55<BR>
561.10.3 Thin Ice
57
58</H2>
59
60<P>
61There are a few situations where seemingly harmless use of a borrowed
62reference can lead to problems. These all have to do with implicit
63invocations of the interpreter, which can cause the owner of a
64reference to dispose of it.
65
66<P>
67The first and most important case to know about is using
68<tt class="cfunction">Py_DECREF()</tt> on an unrelated object while borrowing a
69reference to a list item. For instance:
70
71<P>
72<div class="verbatim"><pre>
73void
74bug(PyObject *list)
75{
76 PyObject *item = PyList_GetItem(list, 0);
77
78 PyList_SetItem(list, 1, PyInt_FromLong(0L));
79 PyObject_Print(item, stdout, 0); /* BUG! */
80}
81</pre></div>
82
83<P>
84This function first borrows a reference to <code>list[0]</code>, then
85replaces <code>list[1]</code> with the value <code>0</code>, and finally prints
86the borrowed reference. Looks harmless, right? But it's not!
87
88<P>
89Let's follow the control flow into <tt class="cfunction">PyList_SetItem()</tt>. The list
90owns references to all its items, so when item 1 is replaced, it has
91to dispose of the original item 1. Now let's suppose the original
92item 1 was an instance of a user-defined class, and let's further
93suppose that the class defined a <tt class="method">__del__()</tt> method. If this
94class instance has a reference count of 1, disposing of it will call
95its <tt class="method">__del__()</tt> method.
96
97<P>
98Since it is written in Python, the <tt class="method">__del__()</tt> method can execute
99arbitrary Python code. Could it perhaps do something to invalidate
100the reference to <code>item</code> in <tt class="cfunction">bug()</tt>? You bet! Assuming
101that the list passed into <tt class="cfunction">bug()</tt> is accessible to the
102<tt class="method">__del__()</tt> method, it could execute a statement to the effect of
103"<tt class="samp">del list[0]</tt>", and assuming this was the last reference to that
104object, it would free the memory associated with it, thereby
105invalidating <code>item</code>.
106
107<P>
108The solution, once you know the source of the problem, is easy:
109temporarily increment the reference count. The correct version of the
110function reads:
111
112<P>
113<div class="verbatim"><pre>
114void
115no_bug(PyObject *list)
116{
117 PyObject *item = PyList_GetItem(list, 0);
118
119 Py_INCREF(item);
120 PyList_SetItem(list, 1, PyInt_FromLong(0L));
121 PyObject_Print(item, stdout, 0);
122 Py_DECREF(item);
123}
124</pre></div>
125
126<P>
127This is a true story. An older version of Python contained variants
128of this bug and someone spent a considerable amount of time in a C
129debugger to figure out why his <tt class="method">__del__()</tt> methods would fail...
130
131<P>
132The second case of problems with a borrowed reference is a variant
133involving threads. Normally, multiple threads in the Python
134interpreter can't get in each other's way, because there is a global
135lock protecting Python's entire object space. However, it is possible
136to temporarily release this lock using the macro
137Py_BEGIN_ALLOW_THREADS, and to re-acquire it using
138Py_END_ALLOW_THREADS. This is common around blocking
139I/O calls, to let other threads use the processor while waiting for
140the I/O to complete. Obviously, the following function has the same
141problem as the previous one:
142
143<P>
144<div class="verbatim"><pre>
145void
146bug(PyObject *list)
147{
148 PyObject *item = PyList_GetItem(list, 0);
149 Py_BEGIN_ALLOW_THREADS
150 ...some blocking I/O call...
151 Py_END_ALLOW_THREADS
152 PyObject_Print(item, stdout, 0); /* BUG! */
153}
154</pre></div>
155
156<P>
157
158<DIV CLASS="navigation">
159<div class='online-navigation'>
160<p></p><hr />
161<table align="center" width="100%" cellpadding="0" cellspacing="2">
162<tr>
163<td class='online-navigation'><a rel="prev" title="1.10.2 Ownership Rules"
164 href="ownershipRules.html"><img src='../icons/previous.png'
165 border='0' height='32' alt='Previous Page' width='32' /></A></td>
166<td class='online-navigation'><a rel="parent" title="1.10 Reference Counts"
167 href="refcounts.html"><img src='../icons/up.png'
168 border='0' height='32' alt='Up One Level' width='32' /></A></td>
169<td class='online-navigation'><a rel="next" title="1.10.4 NULL Pointers"
170 href="nullPointers.html"><img src='../icons/next.png'
171 border='0' height='32' alt='Next Page' width='32' /></A></td>
172<td align="center" width="100%">Extending and Embedding the Python Interpreter</td>
173<td class='online-navigation'><a rel="contents" title="Table of Contents"
174 href="contents.html"><img src='../icons/contents.png'
175 border='0' height='32' alt='Contents' width='32' /></A></td>
176<td class='online-navigation'><img src='../icons/blank.png'
177 border='0' height='32' alt='' width='32' /></td>
178<td class='online-navigation'><img src='../icons/blank.png'
179 border='0' height='32' alt='' width='32' /></td>
180</tr></table>
181<div class='online-navigation'>
182<b class="navlabel">Previous:</b>
183<a class="sectref" rel="prev" href="ownershipRules.html">1.10.2 Ownership Rules</A>
184<b class="navlabel">Up:</b>
185<a class="sectref" rel="parent" href="refcounts.html">1.10 Reference Counts</A>
186<b class="navlabel">Next:</b>
187<a class="sectref" rel="next" href="nullPointers.html">1.10.4 NULL Pointers</A>
188</div>
189</div>
190<hr />
191<span class="release-info">Release 2.4.2, documentation updated on 28 September 2005.</span>
192</DIV>
193<!--End of Navigation Panel-->
194<ADDRESS>
195See <i><a href="about.html">About this document...</a></i> for information on suggesting changes.
196</ADDRESS>
197</BODY>
198</HTML>