diff options
-rw-r--r-- | Cython/Compiler/Nodes.py | 5 | ||||
-rw-r--r-- | tests/memoryview/memoryview.pyx | 33 |
2 files changed, 38 insertions, 0 deletions
diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 977cc12a7..12fdc65b7 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -3740,6 +3740,11 @@ class DefNodeWrapper(FuncDefNode): code.put_var_xdecref_clear(self.starstar_arg.entry) else: code.put_var_decref_clear(self.starstar_arg.entry) + for arg in self.args: + if not arg.type.is_pyobject and arg.type.needs_refcounting: + # at the moment this just catches memoryviewslices, but in future + # other non-PyObject reference counted types might need cleanup + code.put_var_xdecref(arg.entry) code.put_add_traceback(self.target.entry.qualified_name) code.put_finish_refcount_context() code.putln("return %s;" % self.error_value()) diff --git a/tests/memoryview/memoryview.pyx b/tests/memoryview/memoryview.pyx index 273a1fa68..bb8b73780 100644 --- a/tests/memoryview/memoryview.pyx +++ b/tests/memoryview/memoryview.pyx @@ -1172,3 +1172,36 @@ def test_assign_from_byteslike(byteslike): return (<unsigned char*>buf)[:5] finally: free(buf) + +def multiple_memoryview_def(double[:] a, double[:] b): + return a[0] + b[0] + +cpdef multiple_memoryview_cpdef(double[:] a, double[:] b): + return a[0] + b[0] + +cdef multiple_memoryview_cdef(double[:] a, double[:] b): + return a[0] + b[0] + +multiple_memoryview_cdef_wrapper = multiple_memoryview_cdef + +def test_conversion_failures(): + """ + What we're concerned with here is that we don't lose references if one + of several memoryview arguments fails to convert. + + >>> test_conversion_failures() + """ + imb = IntMockBuffer("", range(1), shape=(1,)) + dmb = DoubleMockBuffer("", range(1), shape=(1,)) + for first, second in [(imb, dmb), (dmb, imb)]: + for func in [multiple_memoryview_def, multiple_memoryview_cpdef, multiple_memoryview_cdef_wrapper]: + # note - using python call of "multiple_memoryview_cpdef" deliberately + imb_before = get_refcount(imb) + dmb_before = get_refcount(dmb) + try: + func(first, second) + except: + assert get_refcount(imb) == imb_before, "before %s after %s" % (imb_before, get_refcount(imb)) + assert get_refcount(dmb) == dmb_before, "before %s after %s" % (dmb_before, get_refcount(dmb)) + else: + assert False, "Conversion should fail!" |