diff options
author | Fred Drake <fdrake@acm.org> | 2001-12-11 19:28:22 (GMT) |
---|---|---|
committer | Fred Drake <fdrake@acm.org> | 2001-12-11 19:28:22 (GMT) |
commit | 145b479508c7730a50e905c219e05c2b6d2450b7 (patch) | |
tree | 798458dedc2b4d65a6ee6020e52313395bf47005 | |
parent | e93e47721582804e0d697d851eb7e6e6b6544be2 (diff) | |
download | cpython-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.tex | 48 |
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} |