Release the Python global interpreter lock while running libguestfs
calls.
We don't release it around guestfs_create() because that is a short
call that just allocates memory. We do release it around
guestfs_close() since that is a potentially long-running (it can call
wait(2) amongst other things). We also release it around all the
other generated Python calls.
We don't yet support callbacks into Python code (ie. the new event
API). But when we do in future, we will need to also handle the GIL
around those callbacks.
This code is adapted from libvirt's python/typewrappers.h. Thanks to
Dan Berrange for showing us how to do this properly.
static PyObject *
py_guestfs_close (PyObject *self, PyObject *args)
{
static PyObject *
py_guestfs_close (PyObject *self, PyObject *args)
{
+ PyThreadState *py_save = NULL;
PyObject *py_g;
guestfs_h *g;
PyObject *py_g;
guestfs_h *g;
return NULL;
g = get_handle (py_g);
return NULL;
g = get_handle (py_g);
+ if (PyEval_ThreadsInitialized ())
+ py_save = PyEval_SaveThread ();
+ if (PyEval_ThreadsInitialized ())
+ PyEval_RestoreThread (py_save);
Py_INCREF (Py_None);
return Py_None;
Py_INCREF (Py_None);
return Py_None;
pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
pr "{\n";
pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
pr "{\n";
+ pr " PyThreadState *py_save = NULL;\n";
pr " PyObject *py_g;\n";
pr " guestfs_h *g;\n";
pr " PyObject *py_r;\n";
pr " PyObject *py_g;\n";
pr " guestfs_h *g;\n";
pr " PyObject *py_r;\n";
+ (* Release Python GIL while running. This code is from
+ * libvirt/python/typewrappers.h. Thanks to Dan Berrange for
+ * showing us how to do this properly.
+ *)
+ pr " if (PyEval_ThreadsInitialized ())\n";
+ pr " py_save = PyEval_SaveThread ();\n";
+ pr "\n";
+
if optargs = [] then
pr " r = guestfs_%s " name
else
if optargs = [] then
pr " r = guestfs_%s " name
else
generate_c_call_args ~handle:"g" style;
pr ";\n";
generate_c_call_args ~handle:"g" style;
pr ";\n";
+ pr "\n";
+ pr " if (PyEval_ThreadsInitialized ())\n";
+ pr " PyEval_RestoreThread (py_save);\n";
+ pr "\n";
+
List.iter (
function
| Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
List.iter (
function
| Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _