Commit 2a8c7772 authored by Lisandro Dalcin's avatar Lisandro Dalcin

Fix C++ exception handling for nogil functions (with Stephane Drouard)

parent fc96c622
...@@ -2863,6 +2863,7 @@ class SimpleCallNode(CallNode): ...@@ -2863,6 +2863,7 @@ class SimpleCallNode(CallNode):
or func_type.exception_check: or func_type.exception_check:
self.is_temp = 1 self.is_temp = 1
# C++ exception handler # C++ exception handler
self.nogil = env.nogil
if func_type.exception_check == '+': if func_type.exception_check == '+':
if func_type.exception_value is None: if func_type.exception_value is None:
env.use_utility_code(cpp_exception_utility_code) env.use_utility_code(cpp_exception_utility_code)
...@@ -2957,6 +2958,8 @@ class SimpleCallNode(CallNode): ...@@ -2957,6 +2958,8 @@ class SimpleCallNode(CallNode):
func_type.exception_value.entry.cname) func_type.exception_value.entry.cname)
else: else:
raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname raise_py_exception = '%s(); if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError , "Error converting c++ exception.")' % func_type.exception_value.entry.cname
if self.nogil:
raise_py_exception = 'Py_BLOCK_THREADS; %s; Py_UNBLOCK_THREADS' % raise_py_exception
code.putln( code.putln(
"try {%s%s;} catch(...) {%s; %s}" % ( "try {%s%s;} catch(...) {%s; %s}" % (
lhs, lhs,
......
cdef int raise_TypeError() except *:
raise TypeError("custom")
cdef extern from "cpp_exceptions_nogil_helper.h" nogil:
cdef void foo "foo"(int i) except +
cdef void bar "foo"(int i) except +ValueError
cdef void spam"foo"(int i) except +raise_TypeError
def test_foo():
"""
>>> test_foo()
"""
#
foo(0)
foo(0)
with nogil:
foo(0)
foo(0)
#
try:
with nogil:
foo(0)
finally:
pass
#
try:
with nogil:
foo(0)
with nogil:
foo(0)
finally:
pass
#
try:
with nogil:
foo(0)
with nogil:
foo(1)
except:
with nogil:
foo(0)
finally:
with nogil:
foo(0)
pass
#
try:
with nogil:
foo(0)
foo(0)
finally:
pass
#
try:
with nogil:
foo(0)
foo(1)
except:
with nogil:
foo(0)
finally:
with nogil:
foo(0)
pass
#
try:
with nogil:
foo(0)
try:
with nogil:
foo(1)
except:
with nogil:
foo(1)
finally:
with nogil:
foo(0)
pass
except:
with nogil:
foo(0)
finally:
with nogil:
foo(0)
pass
#
try:
with nogil:
foo(0)
try:
with nogil:
foo(1)
except:
with nogil:
foo(1)
finally:
with nogil:
foo(1)
pass
except:
with nogil:
foo(0)
finally:
with nogil:
foo(0)
pass
#
def test_bar():
"""
>>> test_bar()
"""
#
bar(0)
bar(0)
with nogil:
bar(0)
bar(0)
#
try:
with nogil:
bar(0)
finally:
pass
#
try:
with nogil:
bar(0)
with nogil:
bar(0)
finally:
pass
#
try:
with nogil:
bar(0)
with nogil:
bar(1)
except ValueError:
with nogil:
bar(0)
finally:
with nogil:
bar(0)
pass
#
try:
with nogil:
bar(0)
bar(0)
finally:
pass
#
try:
with nogil:
bar(0)
bar(1)
except ValueError:
with nogil:
bar(0)
finally:
with nogil:
bar(0)
pass
#
try:
with nogil:
bar(0)
try:
with nogil:
bar(1)
except ValueError:
with nogil:
bar(1)
finally:
with nogil:
bar(0)
pass
except ValueError:
with nogil:
bar(0)
finally:
with nogil:
bar(0)
pass
#
try:
with nogil:
bar(0)
try:
with nogil:
bar(1)
except ValueError:
with nogil:
bar(1)
finally:
with nogil:
bar(1)
pass
except ValueError:
with nogil:
bar(0)
finally:
with nogil:
bar(0)
pass
#
def test_spam():
"""
>>> test_spam()
"""
#
spam(0)
spam(0)
with nogil:
spam(0)
spam(0)
#
try:
with nogil:
spam(0)
finally:
pass
#
try:
with nogil:
spam(0)
with nogil:
spam(0)
finally:
pass
#
try:
with nogil:
spam(0)
with nogil:
spam(1)
except TypeError:
with nogil:
spam(0)
finally:
with nogil:
spam(0)
pass
#
try:
with nogil:
spam(0)
spam(0)
finally:
pass
#
try:
with nogil:
spam(0)
spam(1)
except TypeError:
with nogil:
spam(0)
finally:
with nogil:
spam(0)
pass
#
try:
with nogil:
spam(0)
try:
with nogil:
spam(1)
except TypeError:
with nogil:
spam(1)
finally:
with nogil:
spam(0)
pass
except TypeError:
with nogil:
spam(0)
finally:
with nogil:
spam(0)
pass
#
try:
with nogil:
spam(0)
try:
with nogil:
spam(1)
except TypeError:
with nogil:
spam(1)
finally:
with nogil:
spam(1)
pass
except TypeError:
with nogil:
spam(0)
finally:
with nogil:
spam(0)
pass
#
void foo(int i) {
if (i==0)
return;
else
throw i;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment