summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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}