]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
pybind/cephfs: increment ref before calling out to c++
authorPatrick Donnelly <pdonnell@ibm.com>
Wed, 5 Mar 2025 16:15:20 +0000 (11:15 -0500)
committerPatrick Donnelly <pdonnell@ibm.com>
Mon, 17 Mar 2025 19:43:23 +0000 (15:43 -0400)
At the time this construction seemed safe since the caller should have a
reference but it could conveivably be the only ref. We don't want the ref count
to reach 0.

Additionally, catch errors so this callback is genuinely noexcept.

Signed-off-by: Patrick Donnelly <pdonnell@ibm.com>
(cherry picked from commit 395263ceb2f351d540359f52694b48b2824e1291)

src/pybind/cephfs/cephfs.pyx

index b6b810c7ca61833befac4b54a770de8409f6d605..6599beb4c274c8774f64856b1b45a2d537007487 100644 (file)
@@ -114,10 +114,14 @@ cdef extern from "Python.h":
 cdef void completion_callback(int rc, const void* out, size_t outlen, const void* outs, size_t outslen, void* ud) nogil:
     # This GIL awkwardness is due to incompatible types with function pointers defined with mds_command2:
     with gil:
-        pyout = (<unsigned char*>out)[:outlen]
-        pyouts = (<unsigned char*>outs)[:outslen]
-        (<object>ud).complete(rc, pyout, pyouts)
-        ref.Py_DECREF(<object>ud)
+        try:
+            pyout = (<unsigned char*>out)[:outlen]
+            pyouts = (<unsigned char*>outs)[:outslen]
+            (<object>ud).complete(rc, pyout, pyouts)
+        except:
+            pass # we can't handle this in any useful way: e.g. which thread should get the exception?
+        finally:
+            ref.Py_DECREF(<object>ud)
 
 class Error(Exception):
     def get_error_code(self):
@@ -2316,6 +2320,7 @@ cdef class LibCephFS(object):
 
 
         try:
+            ref.Py_INCREF(result)
             with nogil:
                 ret = ceph_mds_command2(self.cluster, _mds_spec,
                                         <const char **>_cmd, _cmdlen,
@@ -2323,9 +2328,8 @@ cdef class LibCephFS(object):
                                         _one_shot,
                                         completion_callback,
                                         <void*>result)
-            if ret == 0:
-                ref.Py_INCREF(result)
-            else:
+            if ret != 0:
+                ref.Py_DECREF(result)
                 raise make_ex(ret, "error in mds_command2")
         finally:
             free(_cmd)