From f0ca61d4a20002497d8e6216a04087ad43a9274a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Mat=C4=9Bj=20Laitl?= Date: Sat, 30 Mar 2013 17:13:47 +0100 Subject: [PATCH] Naive approach to fix memview incref/decref asymmetry in transpose This patch contains test-case along with a blind patch that fixes the test (but may have other consequences, someone who actually understands the code must review it). Original error was: Fatal Python error: Acquisition count is 0 (line XYZ) which was caused by refcount error when memview transposition was used on extension class memoryview attribute. --- Cython/Compiler/ExprNodes.py | 10 ++++++++++ tests/memoryview/transpose_refcount.pyx | 29 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 tests/memoryview/transpose_refcount.pyx diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 08150c4..66e7359 100755 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -5254,6 +5254,16 @@ class AttributeNode(ExprNode): # C method implemented as function call with utility code code.globalstate.use_utility_code(self.entry.utility_code) + def generate_disposal_code(self, code): + if self.is_temp and self.type.is_memoryviewslice and self.is_memslice_transpose: + # mirror condition for putting the memview incref here: + if self.obj.is_name or (self.obj.is_attribute and + self.obj.is_memslice_transpose): + code.put_xdecref_memoryviewslice( + self.result(), have_gil=True) + else: + ExprNode.generate_disposal_code(self, code) + def generate_assignment_code(self, rhs, code): self.obj.generate_evaluation_code(code) if self.is_py_attr: diff --git a/tests/memoryview/transpose_refcount.pyx b/tests/memoryview/transpose_refcount.pyx new file mode 100644 index 0000000..207bf53 --- /dev/null +++ b/tests/memoryview/transpose_refcount.pyx @@ -0,0 +1,29 @@ +# mode: run + +from cython cimport view + +cdef bint print_upper_right(double[:, :] M): + print M[0, 1] + +cdef class MemViewContainer: + cdef double[:, :] A + + def __init__(self, A): + self.A = A + + cpdef run(self): + print_upper_right(self.A) + print_upper_right(self.A.T) + print_upper_right(self.A.T) + +def test_transpose_refcount(): + """ + >>> test_transpose_refcount() + 2.0 + 3.0 + 3.0 + """ + cdef double[:, :] A = view.array(shape=(2, 2), itemsize=sizeof(double), format="d") + A[0, 0], A[0, 1], A[1, 0], A[1, 1] = 1., 2., 3., 4. + cdef MemViewContainer container = MemViewContainer(A) + container.run() -- 2.7.4