summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFred Drake <fdrake@acm.org>2001-12-11 19:28:22 (GMT)
committerFred Drake <fdrake@acm.org>2001-12-11 19:28:22 (GMT)
commit145b479508c7730a50e905c219e05c2b6d2450b7 (patch)
tree798458dedc2b4d65a6ee6020e52313395bf47005
parente93e47721582804e0d697d851eb7e6e6b6544be2 (diff)
downloadcpython-145b479508c7730a50e905c219e05c2b6d2450b7.zip
cpython-145b479508c7730a50e905c219e05c2b6d2450b7.tar.gz
cpython-145b479508c7730a50e905c219e05c2b6d2450b7.tar.bz2
Added discussion of protecting against screwing up the exception state in
an object's deallocator, including an example of how to do this.
-rw-r--r--Doc/ext/newtypes.tex48
1 files changed, 48 insertions, 0 deletions
diff --git a/Doc/ext/newtypes.tex b/Doc/ext/newtypes.tex
index 17e2b25..6ae9f09 100644
--- a/Doc/ext/newtypes.tex
+++ b/Doc/ext/newtypes.tex
@@ -449,6 +449,11 @@ will implement.
\subsection{Finalization and De-allocation}
+\index{object!deallocation}
+\index{deallocation, object}
+\index{object!finalization}
+\index{finalization, of objects}
+
\begin{verbatim}
destructor tp_dealloc;
\end{verbatim}
@@ -468,6 +473,49 @@ newdatatype_dealloc(newdatatypeobject * obj)
}
\end{verbatim}
+One important requirement of the deallocator function is that it
+leaves any pending exceptions alone. This is important since
+deallocators are frequently called as the interpreter unwinds the
+Python stack; when the stack is unwound due to an exception (rather
+than normal returns), nothing is done to protect the deallocators from
+seeing that an exception has already been set. Any actions which a
+deallocator performs which may cause additional Python code to be
+executed may detect that an exception has been set. This can lead to
+misleading errors from the interpreter. The proper way to protect
+against this is to save a pending exception before performing the
+unsafe action, and restoring it when done. This can be done using the
+\cfunction{PyErr_Fetch()}\ttindex{PyErr_Fetch()} and
+\cfunction{PyErr_Restore()}\ttindex{PyErr_Restore()} functions:
+
+\begin{verbatim}
+static void
+my_dealloc(PyObject *obj)
+{
+ MyObject *self = (MyObject *) obj;
+ PyObject *cbresult;
+
+ if (self->my_callback != NULL) {
+ PyObject *err_type, *err_value, *err_traceback;
+ int have_error = PyErr_Occurred() ? 1 : 0;
+
+ if (have_error)
+ PyErr_Fetch(&err_type, &err_value, &err_traceback);
+
+ cbresult = PyObject_CallObject(self->my_callback, NULL);
+ if (cbresult == NULL)
+ PyErr_WriteUnraisable();
+ else
+ Py_DECREF(cbresult);
+
+ if (have_error)
+ PyErr_Restore(err_type, err_value, err_traceback);
+
+ Py_DECREF(self->my_callback);
+ }
+ PyObject_DEL(obj);
+}
+\end{verbatim}
+
\subsection{Object Representation}