Merge branch 'coleb-python35_dtor_exception_fix'

* coleb-python35_dtor_exception_fix:
  Add test case for Python 3.5 assertion with a pending StopIteration
  Amend python_destructor_exception runtime test
  Call PyErr_WriteUnraisable if a destructor sets a Python exception (-builtin)
  Extended zjturner's changes to encompass all function dispatch and use PyErr_WriteUnraisable to handle exceptions during __del__.
  Python - Save and restore exception state before calling destroy.
This commit is contained in:
William S Fulton 2015-12-16 12:58:01 +00:00
commit b15ad9349e
5 changed files with 118 additions and 10 deletions

View file

@ -58,6 +58,7 @@ CPP_TEST_CASES += \
primitive_types \
python_abstractbase \
python_append \
python_destructor_exception \
python_director \
python_docstring \
python_nondynamic \

View file

@ -0,0 +1,64 @@
import python_destructor_exception
from StringIO import StringIO
import sys
def error_function():
python_destructor_exception.ClassWithThrowingDestructor().GetBlah()
def runtest():
attributeErrorOccurred = False
try:
error_function()
except AttributeError, e:
attributeErrorOccurred = True
return attributeErrorOccurred
def test1():
stderr_saved = sys.stderr
buffer = StringIO()
attributeErrorOccurred = False
try:
# Suppress stderr while making this call to suppress the output shown by PyErr_WriteUnraisable
sys.stderr = buffer
attributeErrorOccurred = runtest()
finally:
sys.stderr.flush()
sys.stderr = stderr_saved
assert attributeErrorOccurred
assert buffer.getvalue().count("I am the ClassWithThrowingDestructor dtor doing bad things") >= 1
class VectorHolder(object):
def __init__(self, v):
self.v = v
def gen(self):
for e in self.v:
yield e
# See issue #559, #560, #573 - In Python 3.5, test2() call to the generator 'gen' was
# resulting in the following (not for -builtin where there is no call to SWIG_Python_CallFunctor
# as SwigPyObject_dealloc is not used):
#
# StopIteration
#
# During handling of the above exception, another exception occurred:
# ...
# SystemError: <built-in function delete_VectorInt> returned a result with an error set
def addup():
sum = 0
for i in VectorHolder(python_destructor_exception.VectorInt([1, 2, 3])).gen():
sum = sum + i
return sum
def test2():
sum = addup()
if sum != 6:
raise RuntimeError("Sum is incorrect")
# These two tests are different are two different ways to recreate essentially the same problem
# reported by Python 3.5 that an exception was already set when destroying a wrapped object
test1()
test2()