From: Dag Sverre Seljebotn Date: Wed, 15 Apr 2009 19:44:01 +0000 (+0200) Subject: Proper nogil checks for buffer access X-Git-Tag: 0.11.2.rc1~56^2 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=4b5babd80cafbe68c29893bf7671aecfd01cf848;p=cython.git Proper nogil checks for buffer access --- diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 2abce3f3..25f655a5 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -1745,7 +1745,6 @@ class IndexNode(ExprNode): else: self.index = self.index.coerce_to_pyobject(env) self.type = py_object_type - self.gil_check(env) self.is_temp = 1 else: if self.base.type.is_ptr or self.base.type.is_array: @@ -1762,9 +1761,21 @@ class IndexNode(ExprNode): error(self.pos, "Invalid index type '%s'" % self.index.type) + self.gil_check(env) gil_message = "Indexing Python object" + def gil_check(self, env): + if self.is_buffer_access and env.nogil: + if env.directives['boundscheck']: + error(self.pos, "Cannot check buffer index bounds without gil; use boundscheck(False) directive") + return + elif self.type.is_pyobject: + error(self.pos, "Cannot access buffer with object dtype without gil") + return + super(IndexNode, self).gil_check(env) + + def check_const_addr(self): self.base.check_const_addr() self.index.check_const() diff --git a/tests/errors/e_bufaccess2.pyx b/tests/errors/e_bufaccess2.pyx index 83104915..24fc68a3 100644 --- a/tests/errors/e_bufaccess2.pyx +++ b/tests/errors/e_bufaccess2.pyx @@ -1,8 +1,35 @@ cimport e_bufaccess_pxd # was needed to provoke a bug involving ErrorType +import cython def f(): cdef object[e_bufaccess_pxd.T] buf +def withnogil_access_fail(): + cdef object[int] buf = None + with nogil: + buf[2] = 2 + +@cython.boundscheck(False) +def withnogil_access_ok(): + cdef object[int] buf = None + with nogil: + buf[2] = 2 # No error should be triggered here + +@cython.boundscheck(False) +def withnogil_access_fail_2(): + cdef object[object] buf = None + with nogil: + buf[2] = 2 # Not OK as dtype is object + +def withnogil_acquire(x): + cdef object[int] buf + with nogil: + buf = x + _ERRORS = u""" 3:9: 'nothing' is not a type identifier +10:11: Cannot check buffer index bounds without gil; use boundscheck(False) directive +22:11: Cannot access buffer with object dtype without gil +22:11: Assignment of Python object not allowed without gil +27:12: Assignment of Python object not allowed without gil """ diff --git a/tests/run/bufaccess.pyx b/tests/run/bufaccess.pyx index 50b4e673..81d2238d 100644 --- a/tests/run/bufaccess.pyx +++ b/tests/run/bufaccess.pyx @@ -1449,3 +1449,18 @@ def complex_struct_inplace(object[LongComplex] buf): buf[0].imag += 2 print buf[0].real, buf[0].imag +# +# Nogil +# +@testcase +@cython.boundscheck(False) +def buffer_nogil(): + """ + >>> buffer_nogil() + 10 + """ + cdef object[int] buf = IntMockBuffer(None, [1,2,3]) + with nogil: + buf[1] = 10 + return buf[1] +