[Libguestfs] [libnbd PATCH v3 1/5] python: Simplify passing of mutable *error to callbacks

Eric Blake eblake at redhat.com
Thu Jun 9 20:58:45 UTC 2022


On Thu, Jun 09, 2022 at 11:03:02AM -0500, Eric Blake wrote:
> On Thu, Jun 09, 2022 at 03:22:42PM +0100, Richard W.M. Jones wrote:
> > On Thu, Jun 09, 2022 at 08:34:43AM -0500, Eric Blake wrote:
> > > Instead of open-coding our code to create a PyObject wrapper of the
> > > mutable *error to be passed to each callback, extract this into a
> > > helper function.  We can then slightly optimize things to hang on to a
> > > single pointer to the ctypes module, rather than looking it up on
> > > every callback.  The generated code shrinks by more than the added
> > > code in utils.c:
> > > 
> 
> > > +++ b/generator/Python.ml
> > > @@ -41,6 +41,7 @@ let
> > >  extern PyObject *nbd_internal_py_get_aio_view (PyObject *, bool);
> > >  extern int nbd_internal_py_init_aio_buffer (PyObject *);
> > >  extern PyObject *nbd_internal_py_get_nbd_buffer_type (void);
> > > +extern PyObject *nbd_internal_py_wrap_errptr (int);
> > > 
> > >  static inline struct nbd_handle *
> > >  get_handle (PyObject *obj)
> > > @@ -184,13 +185,7 @@ let
> > >      | CBInt _
> > >      | CBInt64 _ -> ()
> > >      | CBMutable (Int n) ->
> > > -       pr "  PyObject *py_%s_modname = PyUnicode_FromString (\"ctypes\");\n" n;
> > > -       pr "  if (!py_%s_modname) { PyErr_PrintEx (0); goto out; }\n" n;
> > > -       pr "  PyObject *py_%s_mod = PyImport_Import (py_%s_modname);\n" n n;
> > > -       pr "  Py_DECREF (py_%s_modname);\n" n;
> > > -       pr "  if (!py_%s_mod) { PyErr_PrintEx (0); goto out; }\n" n;
> > > -       pr "  py_%s = PyObject_CallMethod (py_%s_mod, \"c_int\", \"i\", *%s);\n" n n n;
> > > -       pr "  Py_DECREF (py_%s_mod);\n" n;
> 
> The old code was using PyObject_CallMethod outside the GIL lock...
> 
> > > +       pr "  py_%s = nbd_internal_py_wrap_errptr (*%s);\n" n n;
> > >         pr "  if (!py_%s) { PyErr_PrintEx (0); goto out; }\n" n;
> > >      | CBString _
> > >      | CBUInt _
> > > diff --git a/python/utils.c b/python/utils.c
> > > index e0df181..cd44b90 100644
> > > --- a/python/utils.c
> > > +++ b/python/utils.c
> > > @@ -173,3 +173,22 @@ nbd_internal_py_get_nbd_buffer_type (void)
> > >    }
> > >    return type;
> > >  }
> > > +
> > > +/* Helper to package callback *error into modifiable PyObject */
> > > +PyObject *
> > > +nbd_internal_py_wrap_errptr (int err)
> > > +{
> > > +  static PyObject *py_ctypes_mod;
> > > +
> > > +  if (!py_ctypes_mod) {
> > > +    PyObject *py_modname = PyUnicode_FromString ("ctypes");
> > > +    if (!py_modname)
> > > +      return NULL;
> > > +    py_ctypes_mod = PyImport_Import (py_modname);
> > > +    Py_DECREF (py_modname);
> > > +    if (!py_ctypes_mod)
> > > +      return NULL;
> 
> ...the new code as well.
> 
> > > +  }
> > > +
> > > +  return PyObject_CallMethod (py_ctypes_mod, "c_int", "i", err);
> > > +}
> > 
> > I guess because of the Python GIL we don't need locking here?
> 
> But you're right that any time we call into the python interpreter for
> something that may entail quite some level of complexity, the GIL lock
> needs to be worried about.  I'll have to audit this and other recent
> patches to see if we need to add more use of
> PyGILState_{Ensure/Release} around various code blocks (after first
> researching what the lock is supposed to do...).

Okay, after reading more about the GIL, it looks like we are (likely)
safe only because we have never really been multi-threaded: none of
our libnbd code uses Py_BEGIN_ALLOW_THREADS to release the GIL around
our calls into libnbd C code, and therefore even though our placement
of PyGILState_Ensure() was too late, all of our callbacks have been
reached from places where we already had the GIL (well, hopefully
that's true).  At any rate, I'm working on a patch to explicitly
release the GIL around calls into libnbd C code, which means we DO
need to fix our callback wrappers to grab it at the right point.  But
the code in utils.c is indeed safe because of the GIL.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


More information about the Libguestfs mailing list