Extended zjturner's changes to encompass all function dispatch and use PyErr_WriteUnraisable to handle exceptions during __del__.
Also added test cases for the unnamed temporary destruction that is throwing assertions in Python 3.5.
This commit is contained in:
parent
2fa9454c9f
commit
a863e98874
4 changed files with 48 additions and 7 deletions
|
|
@ -58,6 +58,7 @@ CPP_TEST_CASES += \
|
|||
primitive_types \
|
||||
python_abstractbase \
|
||||
python_append \
|
||||
python_destructor_exception \
|
||||
python_director \
|
||||
python_docstring \
|
||||
python_nondynamic \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
import python_destructor_exception
|
||||
from StringIO import StringIO
|
||||
import sys
|
||||
|
||||
#buffer = StringIO()
|
||||
#sys.stderr = buffer
|
||||
|
||||
attributeErrorOccurred = False
|
||||
try:
|
||||
python_destructor_exception.ClassWithThrowingDestructor().GetBlah()
|
||||
except AttributeError, e:
|
||||
attributeErrorOccurred = True
|
||||
|
||||
assert attributeErrorOccurred
|
||||
17
Examples/test-suite/python_destructor_exception.i
Normal file
17
Examples/test-suite/python_destructor_exception.i
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/* File : example.i */
|
||||
%module python_destructor_exception
|
||||
%include exception.i
|
||||
|
||||
%exception ClassWithThrowingDestructor::~ClassWithThrowingDestructor()
|
||||
{
|
||||
$action
|
||||
SWIG_exception(SWIG_RuntimeError, "I am the ClassWithThrowingDestructor dtor doing bad things");
|
||||
}
|
||||
|
||||
%inline %{
|
||||
class ClassWithThrowingDestructor
|
||||
{
|
||||
};
|
||||
|
||||
%}
|
||||
|
||||
|
|
@ -536,23 +536,32 @@ SwigPyObject_dealloc(PyObject *v)
|
|||
if (destroy) {
|
||||
/* destroy is always a VARARGS method */
|
||||
PyObject *res;
|
||||
|
||||
/* PyObject_CallFunction() has the potential to silently drop
|
||||
the active active exception. In cases of unnamed temporary
|
||||
variable or where we just finished iterating over a generator
|
||||
StopIteration will be active right now, and this needs to
|
||||
remain true upon return from SwigPyObject_dealloc. So save
|
||||
and restore. */
|
||||
|
||||
PyObject *val = NULL, *type = NULL, *tb = NULL;
|
||||
PyErr_Fetch(&val, &type, &tb);
|
||||
|
||||
if (data->delargs) {
|
||||
/* we need to create a temporary object to carry the destroy operation */
|
||||
PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
|
||||
/* PyObject_CallFunction() has the potential to silently drop the active
|
||||
active exception. In cases where we just finished iterating over a
|
||||
generator StopIteration will be active right now, and this needs to
|
||||
remain true upon return from SwigPyObject_dealloc. So save and restore. */
|
||||
PyObject *val = NULL, *type = NULL, *tb = NULL;
|
||||
PyErr_Fetch(&val, &type, &tb);
|
||||
res = SWIG_Python_CallFunctor(destroy, tmp);
|
||||
PyErr_Restore(val, type, tb);
|
||||
Py_DECREF(tmp);
|
||||
} else {
|
||||
PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
|
||||
PyObject *mself = PyCFunction_GET_SELF(destroy);
|
||||
res = ((*meth)(mself, v));
|
||||
}
|
||||
if (!res)
|
||||
PyErr_WriteUnraisable(destroy);
|
||||
|
||||
PyErr_Restore(val, type, tb);
|
||||
|
||||
Py_XDECREF(res);
|
||||
}
|
||||
#if !defined(SWIG_PYTHON_SILENT_MEMLEAK)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue