always INCREF Python arguments in 'with gil' C functions as we cannot know who owns...
authorStefan Behnel <scoder@users.berlios.de>
Mon, 27 Dec 2010 09:05:37 +0000 (10:05 +0100)
committerStefan Behnel <scoder@users.berlios.de>
Mon, 27 Dec 2010 09:05:37 +0000 (10:05 +0100)
Cython/Compiler/Nodes.py
tests/run/owned_arg_refs.pyx

index 4a0b65bbada1bae04d8c1319ba850624ce64a5ee..41b55d6c37e44b2afc91dc21881660b594e090a6 100644 (file)
@@ -1353,7 +1353,7 @@ class FuncDefNode(StatNode, BlockNode):
         # incref it to properly keep track of refcounts.
         for entry in lenv.arg_entries:
             if entry.type.is_pyobject:
-                if entry.assignments and not entry.in_closure:
+                if (acquire_gil or entry.assignments) and not entry.in_closure:
                     code.put_var_incref(entry)
         # ----- Initialise local variables
         for entry in lenv.var_entries:
@@ -1463,7 +1463,7 @@ class FuncDefNode(StatNode, BlockNode):
             if entry.type.is_pyobject:
                 if entry.in_closure:
                     code.put_var_giveref(entry)
-                elif entry.assignments:
+                elif acquire_gil or entry.assignments:
                     code.put_var_decref(entry)
         if self.needs_closure:
             code.put_decref(Naming.cur_scope_cname, lenv.scope_class.type)
index 5bf84d764952d23e8b577264b1873eb51266c3e8..69058adad5430c451a89bb86167bcb1356133f78 100644 (file)
@@ -15,6 +15,24 @@ def test_ext_type_attr():
     owner.x = ''.join("abc%d" % 5) # non-interned object
     return call_me_with_owner(owner, owner.x)
 
+
+cdef void call_me_without_gil(Owner owner, x) with gil:
+    owner.x = "def" # overwrite external reference
+    print x         # crashes if x is not owned by function or caller
+
+def test_ext_type_attr_nogil():
+    """
+    >>> test_ext_type_attr_nogil()
+    abc5
+    """
+    owner = Owner()
+    owner.x = ''.join("abc%d" % 5) # non-interned object
+    with nogil:
+        call_me_without_gil(owner, owner.x)
+
+
+# the following isn't dangerous as long as index access uses temps
+
 cdef call_me_with_list(list l, x):
     l[:] = [(1,2), (3,4)] # overwrite external reference
     return x              # crashes if x is not owned by function or caller