Commit 49e7d509 authored by Mark Florisson's avatar Mark Florisson

Acquire GIL in nogil contexts to raise UnboundLocalError for unbound memoryview slices

parent a55ce63c
......@@ -1784,12 +1784,16 @@ class CCodeWriter(object):
# return self.putln("if (unlikely(%s < 0)) %s" % (value, self.error_goto(pos))) # TODO this path is almost _never_ taken, yet this macro makes is slower!
return self.putln("if (%s < 0) %s" % (value, self.error_goto(pos)))
def put_error_if_unbound(self, pos, entry):
def put_error_if_unbound(self, pos, entry, in_nogil_context=False):
import ExprNodes
if entry.from_closure:
func = '__Pyx_RaiseClosureNameError'
self.globalstate.use_utility_code(
ExprNodes.raise_closure_name_error_utility_code)
elif entry.type.is_memoryviewslice and in_nogil_context:
func = '__Pyx_RaiseUnboundMemoryviewSliceNogil'
self.globalstate.use_utility_code(
ExprNodes.raise_unbound_memoryview_utility_code_nogil)
else:
func = '__Pyx_RaiseUnboundLocalError'
self.globalstate.use_utility_code(
......
......@@ -1704,7 +1704,7 @@ class NameNode(AtomicExprNode):
memslice_check = entry.type.is_memoryviewslice and self.initialized_check
if null_code and raise_unbound and (entry.type.is_pyobject or memslice_check):
code.put_error_if_unbound(self.pos, entry)
code.put_error_if_unbound(self.pos, entry, self.in_nogil_context)
def generate_assignment_code(self, rhs, code):
#print "NameNode.generate_assignment_code:", self.name ###
......@@ -9670,6 +9670,24 @@ static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname) {
}
""")
# Don't inline the function, it should really never be called in production
raise_unbound_memoryview_utility_code_nogil = UtilityCode(
proto = """
static void __Pyx_RaiseUnboundMemoryviewSliceNogil(const char *varname);
""",
impl = """
static void __Pyx_RaiseUnboundMemoryviewSliceNogil(const char *varname) {
#ifdef WITH_THREAD
PyGILState_STATE gilstate = PyGILState_Ensure();
#endif
__Pyx_RaiseUnboundLocalError(varname);
#ifdef WITH_THREAD")
PyGILState_Release(gilstate);
#endif
}
""",
requires = [raise_unbound_local_error_utility_code])
#------------------------------------------------------------------------------------
getitem_dict_utility_code = UtilityCode(
......
......@@ -197,6 +197,17 @@ def test_cdef_attribute():
print ExtClass().mview
@cython.boundscheck(False)
def test_nogil_unbound_localerror():
"""
>>> test_nogil_unbound_localerror()
Traceback (most recent call last):
...
UnboundLocalError: local variable 'm' referenced before assignment
"""
cdef int[:] m
with nogil:
m[0] = 10
def basic_struct(MyStruct[:] mslice):
"""
......
......@@ -2043,3 +2043,4 @@ def test_dtype_object_scalar_assignment():
(<object> m)[:] = SingleObject(3)
assert m[0] == m[4] == m[-1] == 3
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