summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Cole <coleb@eyesopen.com>2015-12-15 08:39:55 -0700
committerBrian Cole <coleb@eyesopen.com>2015-12-15 08:39:55 -0700
commita863e98874ab751eb9d75677c51449e5c9cea6c3 (patch)
treef0d05865d884f345e115cd3fd0111c85ad3afe2c
parent2fa9454c9ff0bef874363bfec4a2d543ead41bf0 (diff)
downloadswig-a863e98874ab751eb9d75677c51449e5c9cea6c3.tar.gz
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.
-rw-r--r--Examples/test-suite/python/Makefile.in1
-rw-r--r--Examples/test-suite/python/python_destructor_exception_runme.py14
-rw-r--r--Examples/test-suite/python_destructor_exception.i17
-rw-r--r--Lib/python/pyrun.swg23
4 files changed, 48 insertions, 7 deletions
diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in
index 47535f569..096e624ac 100644
--- a/Examples/test-suite/python/Makefile.in
+++ b/Examples/test-suite/python/Makefile.in
@@ -58,6 +58,7 @@ CPP_TEST_CASES += \
primitive_types \
python_abstractbase \
python_append \
+ python_destructor_exception \
python_director \
python_docstring \
python_nondynamic \
diff --git a/Examples/test-suite/python/python_destructor_exception_runme.py b/Examples/test-suite/python/python_destructor_exception_runme.py
new file mode 100644
index 000000000..a19b48633
--- /dev/null
+++ b/Examples/test-suite/python/python_destructor_exception_runme.py
@@ -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
diff --git a/Examples/test-suite/python_destructor_exception.i b/Examples/test-suite/python_destructor_exception.i
new file mode 100644
index 000000000..4d2745ac8
--- /dev/null
+++ b/Examples/test-suite/python_destructor_exception.i
@@ -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
+{
+};
+
+%}
+
diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg
index ba9d6ecca..f25d5ab9c 100644
--- a/Lib/python/pyrun.swg
+++ b/Lib/python/pyrun.swg
@@ -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)