Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 145b479

Browse files
committed
Added discussion of protecting against screwing up the exception state in
an object's deallocator, including an example of how to do this.
1 parent e93e477 commit 145b479

1 file changed

Lines changed: 48 additions & 0 deletions

File tree

Doc/ext/newtypes.tex

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,11 @@ \section{Type Methods
449449

450450
\subsection{Finalization and De-allocation}
451451

452+
\index{object!deallocation}
453+
\index{deallocation, object}
454+
\index{object!finalization}
455+
\index{finalization, of objects}
456+
452457
\begin{verbatim}
453458
destructor tp_dealloc;
454459
\end{verbatim}
@@ -468,6 +473,49 @@ \subsection{Finalization and De-allocation}
468473
}
469474
\end{verbatim}
470475

476+
One important requirement of the deallocator function is that it
477+
leaves any pending exceptions alone. This is important since
478+
deallocators are frequently called as the interpreter unwinds the
479+
Python stack; when the stack is unwound due to an exception (rather
480+
than normal returns), nothing is done to protect the deallocators from
481+
seeing that an exception has already been set. Any actions which a
482+
deallocator performs which may cause additional Python code to be
483+
executed may detect that an exception has been set. This can lead to
484+
misleading errors from the interpreter. The proper way to protect
485+
against this is to save a pending exception before performing the
486+
unsafe action, and restoring it when done. This can be done using the
487+
\cfunction{PyErr_Fetch()}\ttindex{PyErr_Fetch()} and
488+
\cfunction{PyErr_Restore()}\ttindex{PyErr_Restore()} functions:
489+
490+
\begin{verbatim}
491+
static void
492+
my_dealloc(PyObject *obj)
493+
{
494+
MyObject *self = (MyObject *) obj;
495+
PyObject *cbresult;
496+
497+
if (self->my_callback != NULL) {
498+
PyObject *err_type, *err_value, *err_traceback;
499+
int have_error = PyErr_Occurred() ? 1 : 0;
500+
501+
if (have_error)
502+
PyErr_Fetch(&err_type, &err_value, &err_traceback);
503+
504+
cbresult = PyObject_CallObject(self->my_callback, NULL);
505+
if (cbresult == NULL)
506+
PyErr_WriteUnraisable();
507+
else
508+
Py_DECREF(cbresult);
509+
510+
if (have_error)
511+
PyErr_Restore(err_type, err_value, err_traceback);
512+
513+
Py_DECREF(self->my_callback);
514+
}
515+
PyObject_DEL(obj);
516+
}
517+
\end{verbatim}
518+
471519

472520
\subsection{Object Representation}
473521

0 commit comments

Comments
 (0)