Commit 0da93240 authored by Mark Florisson's avatar Mark Florisson

Lock around error info decrefs in nogil try/finally

parent 86be47c1
...@@ -5488,10 +5488,16 @@ class TryFinallyStatNode(StatNode): ...@@ -5488,10 +5488,16 @@ class TryFinallyStatNode(StatNode):
over_label = code.new_label() over_label = code.new_label()
code.put_goto(over_label) code.put_goto(over_label)
code.put_label(finally_error_label) code.put_label(finally_error_label)
code.putln("if (__pyx_why == %d) {" % (error_label_case + 1)) code.putln("if (__pyx_why == %d) {" % (error_label_case + 1))
if self.is_try_finally_in_nogil:
code.put_ensure_gil(declare_gilstate=False)
for var in Naming.exc_vars: for var in Naming.exc_vars:
code.putln("Py_XDECREF(%s);" % var) code.putln("Py_XDECREF(%s);" % var)
if self.is_try_finally_in_nogil:
code.put_release_ensured_gil()
code.putln("}") code.putln("}")
code.put_goto(old_error_label) code.put_goto(old_error_label)
code.put_label(over_label) code.put_label(over_label)
...@@ -5543,7 +5549,8 @@ class TryFinallyStatNode(StatNode): ...@@ -5543,7 +5549,8 @@ class TryFinallyStatNode(StatNode):
def put_error_uncatcher(self, code, i, error_label): def put_error_uncatcher(self, code, i, error_label):
code.globalstate.use_utility_code(restore_exception_utility_code) code.globalstate.use_utility_code(restore_exception_utility_code)
code.putln("case %s: {" % i) code.putln(
"case %s: {" % i)
if self.is_try_finally_in_nogil: if self.is_try_finally_in_nogil:
code.put_ensure_gil(declare_gilstate=False) code.put_ensure_gil(declare_gilstate=False)
...@@ -5555,10 +5562,12 @@ class TryFinallyStatNode(StatNode): ...@@ -5555,10 +5562,12 @@ class TryFinallyStatNode(StatNode):
code.put_release_ensured_gil() code.put_release_ensured_gil()
for var in Naming.exc_vars: for var in Naming.exc_vars:
code.putln("%s = 0;" % var) code.putln(
"%s = 0;" % var)
code.put_goto(error_label) code.put_goto(error_label)
code.putln("}") code.putln(
"}")
def annotate(self, code): def annotate(self, code):
self.body.annotate(code) self.body.annotate(code)
......
...@@ -157,6 +157,6 @@ _ERRORS = u""" ...@@ -157,6 +157,6 @@ _ERRORS = u"""
59:17: Truth-testing Python object not allowed without gil 59:17: Truth-testing Python object not allowed without gil
61:8: For-loop using object bounds or target not allowed without gil 61:8: For-loop using object bounds or target not allowed without gil
63:8: Try-except statement not allowed without gil 63:8: Try-except statement not allowed without gil
67:8: Try-finally statement not allowed without gil 67:8: Cannot use try/finally in nogil sections unless it contains a 'with gil' statement.
84:8: For-loop using object bounds or target not allowed without gil 84:8: For-loop using object bounds or target not allowed without gil
""" """
...@@ -387,3 +387,48 @@ def test_nogil_try_finally_propagate_exception(): ...@@ -387,3 +387,48 @@ def test_nogil_try_finally_propagate_exception():
puts("Execute finally clause") puts("Execute finally clause")
except Exception, e: except Exception, e:
print e print e
def test_nogil_try_finally_return_in_with_gil(x):
"""
>>> test_nogil_try_finally_return_in_with_gil(10)
(None, None, None)
10
"""
# For some reason, this exception is set, clear it first
# (<type 'exceptions.ImportError'>,
# ImportError('cannot import name _TextTestResult',),
# <traceback object at 0x10073c4d0>)
sys.exc_clear()
with nogil:
try:
with gil:
raise Exception("Swallow me!")
finally:
with gil:
print sys.exc_info()
return x
print "I am not executed", sys.exc_info()
cdef void nogil_try_finally_return() nogil:
try:
with gil:
raise Exception("I am swallowed in nogil code... right?")
finally:
with gil:
print sys.exc_info()
return
with gil:
print "I am not executed", sys.exc_info()
def test_nogil_try_finally_return():
"""
>>> test_nogil_try_finally_return()
(None, None, None)
"""
sys.exc_clear()
with nogil:
nogil_try_finally_return()
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