diff options
author | Brian Cole <coleb@eyesopen.com> | 2015-12-15 08:39:55 -0700 |
---|---|---|
committer | Brian Cole <coleb@eyesopen.com> | 2015-12-15 08:39:55 -0700 |
commit | a863e98874ab751eb9d75677c51449e5c9cea6c3 (patch) | |
tree | f0d05865d884f345e115cd3fd0111c85ad3afe2c | |
parent | 2fa9454c9ff0bef874363bfec4a2d543ead41bf0 (diff) | |
download | swig-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.in | 1 | ||||
-rw-r--r-- | Examples/test-suite/python/python_destructor_exception_runme.py | 14 | ||||
-rw-r--r-- | Examples/test-suite/python_destructor_exception.i | 17 | ||||
-rw-r--r-- | Lib/python/pyrun.swg | 23 |
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) |