[pypy-commit] pypy fix-cpyext-releasebuffer: CPyBuffer is used in various places but not all of them needs the additional decref: make sure that we do it only when it's needed, i.e. when we wrap the new style bf_getbuffer

antocuni pypy.commits at gmail.com
Wed Mar 1 10:30:24 EST 2017


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: fix-cpyext-releasebuffer
Changeset: r90443:8229228f828e
Date: 2017-03-01 16:29 +0100
http://bitbucket.org/pypy/pypy/changeset/8229228f828e/

Log:	CPyBuffer is used in various places but not all of them needs the
	additional decref: make sure that we do it only when it's needed,
	i.e. when we wrap the new style bf_getbuffer

diff --git a/pypy/module/cpyext/memoryobject.py b/pypy/module/cpyext/memoryobject.py
--- a/pypy/module/cpyext/memoryobject.py
+++ b/pypy/module/cpyext/memoryobject.py
@@ -72,8 +72,6 @@
     format = 'B'
     if view.c_format:
         format = rffi.charp2str(view.c_format)
-    incref(space, view.c_obj) # we need this incref because
-                              # CPyBuffer.releasebuffer does a decref
     buf = CPyBuffer(space, view.c_buf, view.c_len, from_ref(space, view.c_obj),
                     format=format, shape=shape, strides=strides,
                     ndim=ndim, itemsize=view.c_itemsize,
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -327,8 +327,9 @@
     _immutable_ = True
 
     def __init__(self, space, ptr, size, w_obj, format='B', shape=None,
-                strides=None, ndim=1, itemsize=1, readonly=True,
-                releasebufferproc=rffi.cast(rffi.VOIDP, 0)):
+                 strides=None, ndim=1, itemsize=1, readonly=True,
+                 needs_decref=False,
+                 releasebufferproc=rffi.cast(rffi.VOIDP, 0)):
         self.space = space
         self.ptr = ptr
         self.size = size
@@ -346,14 +347,13 @@
         self.ndim = ndim
         self.itemsize = itemsize
         self.readonly = readonly
+        self.needs_decref = needs_decref
         self.releasebufferproc = releasebufferproc
 
     def releasebuffer(self):
         if self.pyobj:
-            # the CPython docs mandates that you do an incref whenever you
-            # call bf_getbuffer. This is the corresponding decref:
-            #   https://docs.python.org/3.5/c-api/typeobj.html#c.PyBufferProcs.bf_getbuffer
-            decref(self.space, self.pyobj)
+            if self.needs_decref:
+                decref(self.space, self.pyobj)
             self.pyobj = lltype.nullptr(PyObject.TO)
         else:
             #do not call twice
@@ -477,10 +477,15 @@
             format = rffi.charp2str(pybuf.c_format)
         else:
             format = 'B'
+        # the CPython docs mandates that you do an incref whenever you call
+        # bf_getbuffer; so, we pass needs_decref=True to ensure that we don't
+        # leak we release the buffer:
+        # https://docs.python.org/3.5/c-api/typeobj.html#c.PyBufferProcs.bf_getbuffer
         buf = CPyBuffer(space, ptr, size, w_self, format=format,
                             ndim=ndim, shape=shape, strides=strides,
                             itemsize=pybuf.c_itemsize,
                             readonly=widen(pybuf.c_readonly),
+                            needs_decref=True,
                             releasebufferproc = rbp)
         fq.register_finalizer(buf)
         return space.newbuffer(buf)


More information about the pypy-commit mailing list