mirror of
https://github.com/python/cpython.git
synced 2025-11-01 18:51:43 +00:00
Added discussion of protecting against screwing up the exception state in
an object's deallocator, including an example of how to do this.
This commit is contained in:
parent
e93e477215
commit
145b479508
1 changed files with 48 additions and 0 deletions
|
|
@ -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}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue