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:
commit
b15ad9349e
5 changed files with 118 additions and 10 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,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()
|
||||
Loading…
Add table
Add a link
Reference in a new issue