[libvirt] [PATCH] Fix threading problems in python bindings

* libvirt-override.c: Add many missing calls to allow threading when entering C code, otherwise python blocks & then deadlocks when we have an async event to dispatch back into python code --- python/libvirt-override.c | 106 ++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 96 insertions(+), 10 deletions(-) diff --git a/python/libvirt-override.c b/python/libvirt-override.c index b885190..0f7db9c 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c @@ -67,7 +67,10 @@ libvirt_virDomainBlockStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { return(NULL); domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainBlockStats(domain, path, &stats, sizeof(stats)); + LIBVIRT_END_ALLOW_THREADS; + if (c_retval < 0) return VIR_PY_NONE; @@ -96,7 +99,10 @@ libvirt_virDomainInterfaceStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) return(NULL); domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainInterfaceStats(domain, path, &stats, sizeof(stats)); + LIBVIRT_END_ALLOW_THREADS; + if (c_retval < 0) return VIR_PY_NONE; @@ -128,7 +134,9 @@ libvirt_virDomainGetSchedulerType(PyObject *self ATTRIBUTE_UNUSED, return(NULL); domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetSchedulerType(domain, &nparams); + LIBVIRT_END_ALLOW_THREADS; if (c_retval == NULL) return VIR_PY_NONE; @@ -150,6 +158,7 @@ libvirt_virDomainGetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, virDomainPtr domain; PyObject *pyobj_domain, *info; char *c_retval; + int i_retval; int nparams, i; virSchedParameterPtr params; @@ -158,7 +167,10 @@ libvirt_virDomainGetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, return(NULL); domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetSchedulerType(domain, &nparams); + LIBVIRT_END_ALLOW_THREADS; + if (c_retval == NULL) return VIR_PY_NONE; free(c_retval); @@ -166,7 +178,11 @@ libvirt_virDomainGetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, if ((params = malloc(sizeof(*params)*nparams)) == NULL) return VIR_PY_NONE; - if (virDomainGetSchedulerParameters(domain, params, &nparams) < 0) { + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virDomainGetSchedulerParameters(domain, params, &nparams); + LIBVIRT_END_ALLOW_THREADS; + + if (i_retval < 0) { free(params); return VIR_PY_NONE; } @@ -223,6 +239,7 @@ libvirt_virDomainSetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, virDomainPtr domain; PyObject *pyobj_domain, *info; char *c_retval; + int i_retval; int nparams, i; virSchedParameterPtr params; @@ -231,7 +248,10 @@ libvirt_virDomainSetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, return(NULL); domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetSchedulerType(domain, &nparams); + LIBVIRT_END_ALLOW_THREADS; + if (c_retval == NULL) return VIR_PY_INT_FAIL; free(c_retval); @@ -239,7 +259,11 @@ libvirt_virDomainSetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, if ((params = malloc(sizeof(*params)*nparams)) == NULL) return VIR_PY_INT_FAIL; - if (virDomainGetSchedulerParameters(domain, params, &nparams) < 0) { + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virDomainGetSchedulerParameters(domain, params, &nparams); + LIBVIRT_END_ALLOW_THREADS; + + if (i_retval < 0) { free(params); return VIR_PY_INT_FAIL; } @@ -292,7 +316,10 @@ libvirt_virDomainSetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, } } - if (virDomainSetSchedulerParameters(domain, params, nparams) < 0) { + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virDomainSetSchedulerParameters(domain, params, nparams); + LIBVIRT_END_ALLOW_THREADS; + if (i_retval < 0) { free(params); return VIR_PY_INT_FAIL; } @@ -311,13 +338,17 @@ libvirt_virDomainGetVcpus(PyObject *self ATTRIBUTE_UNUSED, virVcpuInfoPtr cpuinfo = NULL; unsigned char *cpumap = NULL; int cpumaplen, i; + int i_retval; if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetVcpus", &pyobj_domain)) return(NULL); domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); - if (virNodeGetInfo(virDomainGetConnect(domain), &nodeinfo) != 0) + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virNodeGetInfo(virDomainGetConnect(domain), &nodeinfo); + LIBVIRT_END_ALLOW_THREADS; + if (i_retval < 0) return VIR_PY_NONE; if (virDomainGetInfo(domain, &dominfo) != 0) @@ -330,9 +361,12 @@ libvirt_virDomainGetVcpus(PyObject *self ATTRIBUTE_UNUSED, if ((cpumap = malloc(dominfo.nrVirtCpu * cpumaplen)) == NULL) goto cleanup; - if (virDomainGetVcpus(domain, - cpuinfo, dominfo.nrVirtCpu, - cpumap, cpumaplen) < 0) + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virDomainGetVcpus(domain, + cpuinfo, dominfo.nrVirtCpu, + cpumap, cpumaplen); + LIBVIRT_END_ALLOW_THREADS; + if (i_retval < 0) goto cleanup; /* convert to a Python tuple of long objects */ @@ -395,13 +429,17 @@ libvirt_virDomainPinVcpu(PyObject *self ATTRIBUTE_UNUSED, virNodeInfo nodeinfo; unsigned char *cpumap; int cpumaplen, i, vcpu; + int i_retval; if (!PyArg_ParseTuple(args, (char *)"OiO:virDomainPinVcpu", &pyobj_domain, &vcpu, &pycpumap)) return(NULL); domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); - if (virNodeGetInfo(virDomainGetConnect(domain), &nodeinfo) != 0) + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virNodeGetInfo(virDomainGetConnect(domain), &nodeinfo); + LIBVIRT_END_ALLOW_THREADS; + if (i_retval < 0) return VIR_PY_INT_FAIL; cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo)); @@ -418,10 +456,15 @@ libvirt_virDomainPinVcpu(PyObject *self ATTRIBUTE_UNUSED, VIR_UNUSE_CPU(cpumap, i); } - virDomainPinVcpu(domain, vcpu, cpumap, cpumaplen); + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virDomainPinVcpu(domain, vcpu, cpumap, cpumaplen); + LIBVIRT_END_ALLOW_THREADS; Py_DECREF(truth); free(cpumap); + if (i_retval < 0) + return VIR_PY_INT_FAIL; + return VIR_PY_INT_SUCCESS; } @@ -471,7 +514,10 @@ libvirt_virConnGetLastError(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) return(NULL); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); - if ((err = virConnGetLastError(conn)) == NULL) + LIBVIRT_BEGIN_ALLOW_THREADS; + err = virConnGetLastError(conn); + LIBVIRT_END_ALLOW_THREADS; + if (err == NULL) return VIR_PY_NONE; if ((info = PyTuple_New(9)) == NULL) @@ -793,7 +839,9 @@ libvirt_virConnectListDefinedDomains(PyObject *self ATTRIBUTE_UNUSED, return(NULL); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfDefinedDomains(conn); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; @@ -801,7 +849,9 @@ libvirt_virConnectListDefinedDomains(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListDefinedDomains(conn, names, c_retval); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; @@ -966,7 +1016,9 @@ libvirt_virConnectListNetworks(PyObject *self ATTRIBUTE_UNUSED, return(NULL); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfNetworks(conn); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; @@ -974,7 +1026,9 @@ libvirt_virConnectListNetworks(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListNetworks(conn, names, c_retval); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; @@ -1008,7 +1062,9 @@ libvirt_virConnectListDefinedNetworks(PyObject *self ATTRIBUTE_UNUSED, return(NULL); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfDefinedNetworks(conn); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; @@ -1016,7 +1072,9 @@ libvirt_virConnectListDefinedNetworks(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListDefinedNetworks(conn, names, c_retval); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; @@ -1211,7 +1269,9 @@ libvirt_virConnectListStoragePools(PyObject *self ATTRIBUTE_UNUSED, return(NULL); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfStoragePools(conn); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; @@ -1219,7 +1279,9 @@ libvirt_virConnectListStoragePools(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListStoragePools(conn, names, c_retval); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; @@ -1261,7 +1323,9 @@ libvirt_virConnectListDefinedStoragePools(PyObject *self ATTRIBUTE_UNUSED, return(NULL); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfDefinedStoragePools(conn); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; @@ -1269,7 +1333,9 @@ libvirt_virConnectListDefinedStoragePools(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListDefinedStoragePools(conn, names, c_retval); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; @@ -1311,7 +1377,9 @@ libvirt_virStoragePoolListVolumes(PyObject *self ATTRIBUTE_UNUSED, return(NULL); pool = (virStoragePoolPtr) PyvirStoragePool_Get(pyobj_pool); + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virStoragePoolNumOfVolumes(pool); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; @@ -1319,7 +1387,9 @@ libvirt_virStoragePoolListVolumes(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virStoragePoolListVolumes(pool, names, c_retval); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; @@ -1520,7 +1590,9 @@ libvirt_virNodeListDevices(PyObject *self ATTRIBUTE_UNUSED, return(NULL); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeNumOfDevices(conn, cap, flags); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; @@ -1528,7 +1600,9 @@ libvirt_virNodeListDevices(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeListDevices(conn, cap, names, c_retval, flags); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; @@ -1560,7 +1634,9 @@ libvirt_virNodeDeviceListCaps(PyObject *self ATTRIBUTE_UNUSED, return(NULL); dev = (virNodeDevicePtr) PyvirNodeDevice_Get(pyobj_dev); + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeDeviceNumOfCaps(dev); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; @@ -1568,7 +1644,9 @@ libvirt_virNodeDeviceListCaps(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeDeviceListCaps(dev, names, c_retval); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; @@ -1775,7 +1853,9 @@ libvirt_virConnectListInterfaces(PyObject *self ATTRIBUTE_UNUSED, return(NULL); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfInterfaces(conn); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; @@ -1783,7 +1863,9 @@ libvirt_virConnectListInterfaces(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListInterfaces(conn, names, c_retval); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; @@ -1826,7 +1908,9 @@ libvirt_virConnectListDefinedInterfaces(PyObject *self ATTRIBUTE_UNUSED, return(NULL); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfDefinedInterfaces(conn); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; @@ -1834,7 +1918,9 @@ libvirt_virConnectListDefinedInterfaces(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListDefinedInterfaces(conn, names, c_retval); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; -- 1.6.5.2

2009/11/25 Daniel P. Berrange <berrange@redhat.com>:
* libvirt-override.c: Add many missing calls to allow threading when entering C code, otherwise python blocks & then deadlocks when we have an async event to dispatch back into python code --- python/libvirt-override.c | 106 ++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 96 insertions(+), 10 deletions(-)
diff --git a/python/libvirt-override.c b/python/libvirt-override.c index b885190..0f7db9c 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c [...] @@ -418,10 +456,15 @@ libvirt_virDomainPinVcpu(PyObject *self ATTRIBUTE_UNUSED, VIR_UNUSE_CPU(cpumap, i); }
- virDomainPinVcpu(domain, vcpu, cpumap, cpumaplen); + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virDomainPinVcpu(domain, vcpu, cpumap, cpumaplen); + LIBVIRT_END_ALLOW_THREADS; Py_DECREF(truth); free(cpumap);
+ if (i_retval < 0) + return VIR_PY_INT_FAIL; + return VIR_PY_INT_SUCCESS; }
You should at least mention this additional fix in the commit message. ACK! Matthias

On Wed, Nov 25, 2009 at 12:06:03PM +0000, Daniel P. Berrange wrote:
* libvirt-override.c: Add many missing calls to allow threading when entering C code, otherwise python blocks & then deadlocks when we have an async event to dispatch back into python code --- python/libvirt-override.c | 106 ++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 96 insertions(+), 10 deletions(-)
diff --git a/python/libvirt-override.c b/python/libvirt-override.c index b885190..0f7db9c 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c @@ -67,7 +67,10 @@ libvirt_virDomainBlockStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { return(NULL); domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+ LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainBlockStats(domain, path, &stats, sizeof(stats)); + LIBVIRT_END_ALLOW_THREADS; + if (c_retval < 0) return VIR_PY_NONE;
@@ -96,7 +99,10 @@ libvirt_virDomainInterfaceStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) return(NULL); domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+ LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainInterfaceStats(domain, path, &stats, sizeof(stats)); + LIBVIRT_END_ALLOW_THREADS; + if (c_retval < 0) return VIR_PY_NONE;
@@ -128,7 +134,9 @@ libvirt_virDomainGetSchedulerType(PyObject *self ATTRIBUTE_UNUSED, return(NULL); domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+ LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetSchedulerType(domain, &nparams); + LIBVIRT_END_ALLOW_THREADS; if (c_retval == NULL) return VIR_PY_NONE;
@@ -150,6 +158,7 @@ libvirt_virDomainGetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, virDomainPtr domain; PyObject *pyobj_domain, *info; char *c_retval; + int i_retval; int nparams, i; virSchedParameterPtr params;
@@ -158,7 +167,10 @@ libvirt_virDomainGetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, return(NULL); domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+ LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetSchedulerType(domain, &nparams); + LIBVIRT_END_ALLOW_THREADS; + if (c_retval == NULL) return VIR_PY_NONE; free(c_retval); @@ -166,7 +178,11 @@ libvirt_virDomainGetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, if ((params = malloc(sizeof(*params)*nparams)) == NULL) return VIR_PY_NONE;
- if (virDomainGetSchedulerParameters(domain, params, &nparams) < 0) { + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virDomainGetSchedulerParameters(domain, params, &nparams); + LIBVIRT_END_ALLOW_THREADS; + + if (i_retval < 0) { free(params); return VIR_PY_NONE; } @@ -223,6 +239,7 @@ libvirt_virDomainSetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, virDomainPtr domain; PyObject *pyobj_domain, *info; char *c_retval; + int i_retval; int nparams, i; virSchedParameterPtr params;
@@ -231,7 +248,10 @@ libvirt_virDomainSetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, return(NULL); domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+ LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetSchedulerType(domain, &nparams); + LIBVIRT_END_ALLOW_THREADS; + if (c_retval == NULL) return VIR_PY_INT_FAIL; free(c_retval); @@ -239,7 +259,11 @@ libvirt_virDomainSetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, if ((params = malloc(sizeof(*params)*nparams)) == NULL) return VIR_PY_INT_FAIL;
- if (virDomainGetSchedulerParameters(domain, params, &nparams) < 0) { + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virDomainGetSchedulerParameters(domain, params, &nparams); + LIBVIRT_END_ALLOW_THREADS; + + if (i_retval < 0) { free(params); return VIR_PY_INT_FAIL; } @@ -292,7 +316,10 @@ libvirt_virDomainSetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, } }
- if (virDomainSetSchedulerParameters(domain, params, nparams) < 0) { + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virDomainSetSchedulerParameters(domain, params, nparams); + LIBVIRT_END_ALLOW_THREADS; + if (i_retval < 0) { free(params); return VIR_PY_INT_FAIL; } @@ -311,13 +338,17 @@ libvirt_virDomainGetVcpus(PyObject *self ATTRIBUTE_UNUSED, virVcpuInfoPtr cpuinfo = NULL; unsigned char *cpumap = NULL; int cpumaplen, i; + int i_retval;
if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetVcpus", &pyobj_domain)) return(NULL); domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
- if (virNodeGetInfo(virDomainGetConnect(domain), &nodeinfo) != 0) + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virNodeGetInfo(virDomainGetConnect(domain), &nodeinfo); + LIBVIRT_END_ALLOW_THREADS; + if (i_retval < 0) return VIR_PY_NONE;
if (virDomainGetInfo(domain, &dominfo) != 0) @@ -330,9 +361,12 @@ libvirt_virDomainGetVcpus(PyObject *self ATTRIBUTE_UNUSED, if ((cpumap = malloc(dominfo.nrVirtCpu * cpumaplen)) == NULL) goto cleanup;
- if (virDomainGetVcpus(domain, - cpuinfo, dominfo.nrVirtCpu, - cpumap, cpumaplen) < 0) + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virDomainGetVcpus(domain, + cpuinfo, dominfo.nrVirtCpu, + cpumap, cpumaplen); + LIBVIRT_END_ALLOW_THREADS; + if (i_retval < 0) goto cleanup;
/* convert to a Python tuple of long objects */ @@ -395,13 +429,17 @@ libvirt_virDomainPinVcpu(PyObject *self ATTRIBUTE_UNUSED, virNodeInfo nodeinfo; unsigned char *cpumap; int cpumaplen, i, vcpu; + int i_retval;
if (!PyArg_ParseTuple(args, (char *)"OiO:virDomainPinVcpu", &pyobj_domain, &vcpu, &pycpumap)) return(NULL); domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
- if (virNodeGetInfo(virDomainGetConnect(domain), &nodeinfo) != 0) + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virNodeGetInfo(virDomainGetConnect(domain), &nodeinfo); + LIBVIRT_END_ALLOW_THREADS; + if (i_retval < 0) return VIR_PY_INT_FAIL;
cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo)); @@ -418,10 +456,15 @@ libvirt_virDomainPinVcpu(PyObject *self ATTRIBUTE_UNUSED, VIR_UNUSE_CPU(cpumap, i); }
- virDomainPinVcpu(domain, vcpu, cpumap, cpumaplen); + LIBVIRT_BEGIN_ALLOW_THREADS; + i_retval = virDomainPinVcpu(domain, vcpu, cpumap, cpumaplen); + LIBVIRT_END_ALLOW_THREADS; Py_DECREF(truth); free(cpumap);
+ if (i_retval < 0) + return VIR_PY_INT_FAIL; + return VIR_PY_INT_SUCCESS; }
@@ -471,7 +514,10 @@ libvirt_virConnGetLastError(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) return(NULL); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
- if ((err = virConnGetLastError(conn)) == NULL) + LIBVIRT_BEGIN_ALLOW_THREADS; + err = virConnGetLastError(conn); + LIBVIRT_END_ALLOW_THREADS; + if (err == NULL) return VIR_PY_NONE;
if ((info = PyTuple_New(9)) == NULL) @@ -793,7 +839,9 @@ libvirt_virConnectListDefinedDomains(PyObject *self ATTRIBUTE_UNUSED, return(NULL); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
+ LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfDefinedDomains(conn); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE;
@@ -801,7 +849,9 @@ libvirt_virConnectListDefinedDomains(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListDefinedDomains(conn, names, c_retval); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; @@ -966,7 +1016,9 @@ libvirt_virConnectListNetworks(PyObject *self ATTRIBUTE_UNUSED, return(NULL); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
+ LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfNetworks(conn); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE;
@@ -974,7 +1026,9 @@ libvirt_virConnectListNetworks(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListNetworks(conn, names, c_retval); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; @@ -1008,7 +1062,9 @@ libvirt_virConnectListDefinedNetworks(PyObject *self ATTRIBUTE_UNUSED, return(NULL); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
+ LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfDefinedNetworks(conn); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE;
@@ -1016,7 +1072,9 @@ libvirt_virConnectListDefinedNetworks(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListDefinedNetworks(conn, names, c_retval); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; @@ -1211,7 +1269,9 @@ libvirt_virConnectListStoragePools(PyObject *self ATTRIBUTE_UNUSED, return(NULL); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
+ LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfStoragePools(conn); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE;
@@ -1219,7 +1279,9 @@ libvirt_virConnectListStoragePools(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListStoragePools(conn, names, c_retval); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; @@ -1261,7 +1323,9 @@ libvirt_virConnectListDefinedStoragePools(PyObject *self ATTRIBUTE_UNUSED, return(NULL); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
+ LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfDefinedStoragePools(conn); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE;
@@ -1269,7 +1333,9 @@ libvirt_virConnectListDefinedStoragePools(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListDefinedStoragePools(conn, names, c_retval); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; @@ -1311,7 +1377,9 @@ libvirt_virStoragePoolListVolumes(PyObject *self ATTRIBUTE_UNUSED, return(NULL); pool = (virStoragePoolPtr) PyvirStoragePool_Get(pyobj_pool);
+ LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virStoragePoolNumOfVolumes(pool); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE;
@@ -1319,7 +1387,9 @@ libvirt_virStoragePoolListVolumes(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virStoragePoolListVolumes(pool, names, c_retval); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; @@ -1520,7 +1590,9 @@ libvirt_virNodeListDevices(PyObject *self ATTRIBUTE_UNUSED, return(NULL); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
+ LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeNumOfDevices(conn, cap, flags); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE;
@@ -1528,7 +1600,9 @@ libvirt_virNodeListDevices(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeListDevices(conn, cap, names, c_retval, flags); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; @@ -1560,7 +1634,9 @@ libvirt_virNodeDeviceListCaps(PyObject *self ATTRIBUTE_UNUSED, return(NULL); dev = (virNodeDevicePtr) PyvirNodeDevice_Get(pyobj_dev);
+ LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeDeviceNumOfCaps(dev); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE;
@@ -1568,7 +1644,9 @@ libvirt_virNodeDeviceListCaps(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeDeviceListCaps(dev, names, c_retval); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; @@ -1775,7 +1853,9 @@ libvirt_virConnectListInterfaces(PyObject *self ATTRIBUTE_UNUSED, return(NULL); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
+ LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfInterfaces(conn); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE;
@@ -1783,7 +1863,9 @@ libvirt_virConnectListInterfaces(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListInterfaces(conn, names, c_retval); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE; @@ -1826,7 +1908,9 @@ libvirt_virConnectListDefinedInterfaces(PyObject *self ATTRIBUTE_UNUSED, return(NULL); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
+ LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfDefinedInterfaces(conn); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE;
@@ -1834,7 +1918,9 @@ libvirt_virConnectListDefinedInterfaces(PyObject *self ATTRIBUTE_UNUSED, names = malloc(sizeof(*names) * c_retval); if (!names) return VIR_PY_NONE; + LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListDefinedInterfaces(conn, names, c_retval); + LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { free(names); return VIR_PY_NONE;
Whoops ... that was a lot of them missing, ACK ! Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Wed, Nov 25, 2009 at 12:06:03PM +0000, Daniel P. Berrange wrote:
* libvirt-override.c: Add many missing calls to allow threading when entering C code, otherwise python blocks & then deadlocks when we have an async event to dispatch back into python code
Thanks, but I am still experiencing deadlocks when I run more than one domain. Thread 3 (Thread 0x52022940 (LWP 29704)): #0 0x0000003cc1c0c9b1 in sem_wait () from /lib64/libpthread.so.0 #1 0x0000003cc24b8148 in PyThread_acquire_lock (lock=<value optimized out>, waitflag=<value optimized out>) at Python/thread_pthread.h:313 #2 0x0000003cc2496084 in PyEval_RestoreThread (tstate=<value optimized out>) at Python/ceval.c:305 #3 0x0000003cc24b1eac in PyGILState_Ensure () at Python/pystate.c:508 #4 0x00002ae384d41605 in libvirt_virEventUpdateHandleFunc (watch=2, event=0) at libvirt-override.c:2279 #5 0x00002ae384fbd016 in remoteIO (conn=0xf57b560, priv=0x2aaaaad7a010, flags=0, thiscall=0x2aaaac0008e0) at remote/remote_driver.c:8437 #6 0x00002ae384fbdbab in call (conn=0xf57b560, priv=0x2aaaaad7a010, flags=0, proc_nr=<value optimized out>, args_filter=0x2ae384fd0af0 <xdr_remote_domain_interface_stats_args>, args=0x52020120 "\220ZX\017", ret_filter=0x2ae384fcdfe0 <xdr_remote_domain_interface_stats_ret>, ret=0x520200e0 "") at remote/remote_driver.c:8508 #7 0x00002ae384fc084b in remoteDomainInterfaceStats (domain=0xf57fdc0, path=0xf630e34 "vnet1", stats=0x520201a0) at remote/remote_driver.c:3345 #8 0x00002ae384fafd82 in virDomainInterfaceStats (dom=0xf57fdc0, path=0xf630e34 "vnet1", stats=0x52020210, size=64) at libvirt.c:4083 #9 0x00002ae384d433e7 in libvirt_virDomainInterfaceStats ( self=<value optimized out>, args=<value optimized out>) at libvirt-override.c:103 #10 0x0000003cc24950ba in PyEval_EvalFrame (f=<value optimized out>) at Python/ceval.c:3563 #11 0x0000003cc2495fe5 in PyEval_EvalCodeEx (co=<value optimized out>, globals=<value optimized out>, locals=<value optimized out>, args=<value optimized out>, argcount=<value optimized out>, kws=<value optimized out>, kwcount=<value optimized out>, defs=<value optimized out>, defcount=<value optimized out>, closure=<value optimized out>) at Python/ceval.c:2736 #12 0x0000003cc244c45a in function_call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/funcobject.c:548 #13 0x0000003cc24360f0 in PyObject_Call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/abstract.c:1795 #14 0x0000003cc249352c in PyEval_EvalFrame (f=<value optimized out>) at Python/ceval.c:3840 #15 0x0000003cc2495fe5 in PyEval_EvalCodeEx (co=<value optimized out>, globals=<value optimized out>, locals=<value optimized out>, args=<value optimized out>, argcount=<value optimized out>, kws=<value optimized out>, kwcount=<value optimized out>, defs=<value optimized out>, defcount=<value optimized out>, closure=<value optimized out>) at Python/ceval.c:2736 #16 0x0000003cc249473f in PyEval_EvalFrame (f=<value optimized out>) at Python/ceval.c:3656 #17 0x0000003cc2495fe5 in PyEval_EvalCodeEx (co=<value optimized out>, globals=<value optimized out>, locals=<value optimized out>, args=<value optimized out>, argcount=<value optimized out>, kws=<value optimized out>, kwcount=<value optimized out>, defs=<value optimized out>, defcount=<value optimized out>, closure=<value optimized out>) at Python/ceval.c:2736 #18 0x0000003cc244c367 in function_call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/funcobject.c:548 #19 0x0000003cc24360f0 in PyObject_Call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/abstract.c:1795 #20 0x0000003cc243c1ef in instancemethod_call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/classobject.c:2447 #21 0x0000003cc24360f0 in PyObject_Call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/abstract.c:1795 #22 0x0000003cc248fc3d in PyEval_CallObjectWithKeywords ( func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Python/ceval.c:3430 #23 0x0000003cc243fc10 in PyInstance_New (klass=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/classobject.c:575 #24 0x0000003cc24360f0 in PyObject_Call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/abstract.c:1795 #25 0x0000003cc24928ce in PyEval_EvalFrame (f=<value optimized out>) at Python/ceval.c:3771 #26 0x0000003cc2495fe5 in PyEval_EvalCodeEx (co=<value optimized out>, globals=<value optimized out>, locals=<value optimized out>, args=<value optimized out>, argcount=<value optimized out>, kws=<value optimized out>, kwcount=<value optimized out>, defs=<value optimized out>, defcount=<value optimized out>, closure=<value optimized out>) at Python/ceval.c:2736 #27 0x0000003cc244c367 in function_call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/funcobject.c:548 #28 0x0000003cc24360f0 in PyObject_Call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/abstract.c:1795 #29 0x0000003cc243c1ef in instancemethod_call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/classobject.c:2447 #30 0x0000003cc24360f0 in PyObject_Call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/abstract.c:1795 #31 0x0000003cc248fc3d in PyEval_CallObjectWithKeywords ( func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Python/ceval.c:3430 #32 0x0000003cc243fc10 in PyInstance_New (klass=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/classobject.c:575 #33 0x0000003cc24360f0 in PyObject_Call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/abstract.c:1795 #34 0x0000003cc24928ce in PyEval_EvalFrame (f=<value optimized out>) at Python/ceval.c:3771 #35 0x0000003cc2494b66 in PyEval_EvalFrame (f=<value optimized out>) at Python/ceval.c:3645 #36 0x0000003cc2494b66 in PyEval_EvalFrame (f=<value optimized out>) at Python/ceval.c:3645 #37 0x0000003cc2495fe5 in PyEval_EvalCodeEx (co=<value optimized out>, globals=<value optimized out>, locals=<value optimized out>, args=<value optimized out>, argcount=<value optimized out>, kws=<value optimized out>, kwcount=<value optimized out>, defs=<value optimized out>, defcount=<value optimized out>, closure=<value optimized out>) at Python/ceval.c:2736 #38 0x0000003cc244c367 in function_call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/funcobject.c:548 #39 0x0000003cc24360f0 in PyObject_Call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/abstract.c:1795 #40 0x0000003cc243c1ef in instancemethod_call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/classobject.c:2447 #41 0x0000003cc24360f0 in PyObject_Call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/abstract.c:1795 #42 0x0000003cc248fc3d in PyEval_CallObjectWithKeywords ( func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Python/ceval.c:3430 #43 0x0000003cc24bbbbd in t_bootstrap (boot_raw=<value optimized out>) at Modules/threadmodule.c:434 #44 0x0000003cc1c064a7 in start_thread () from /lib64/libpthread.so.0 #45 0x0000003cc14d3c2d in clone () from /lib64/libc.so.6 Thread 2 (Thread 0x50c20940 (LWP 29764)): #0 0x0000003cc1c0ab99 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0 #1 0x00002ae384f7dbb6 in virCondWait (c=0xf7e4cdc, m=0x80) at util/threads-pthread.c:84 #2 0x00002ae384fbcf62 in remoteIO (conn=0xf57b560, priv=0x2aaaaad7a010, flags=0, thiscall=0xf7a4cc0) at remote/remote_driver.c:8378 #3 0x00002ae384fbdbab in call (conn=0xf57b560, priv=0x2aaaaad7a010, flags=0, proc_nr=<value optimized out>, args_filter=0x2ae384fd07b0 <xdr_remote_domain_get_info_args>, args=0x50c1e100 "\020{^\017", ret_filter=0x2ae384fcdf60 <xdr_remote_domain_get_info_ret>, ret=0x50c1e0d0 "") at remote/remote_driver.c:8508 #4 0x00002ae384fc1fe0 in remoteDomainGetInfo (domain=0xf5e91f0, info=0x50c1e1c0) at remote/remote_driver.c:2261 #5 0x00002ae384fb023b in virDomainGetInfo (domain=0xf5e91f0, info=0x50c1e1c0) at libvirt.c:2786 #6 0x00002ae384d42748 in libvirt_virDomainGetVcpus ( self=<value optimized out>, args=<value optimized out>) at libvirt-override.c:354 #7 0x0000003cc24950ba in PyEval_EvalFrame (f=<value optimized out>) at Python/ceval.c:3563 #8 0x0000003cc2495fe5 in PyEval_EvalCodeEx (co=<value optimized out>, globals=<value optimized out>, locals=<value optimized out>, args=<value optimized out>, argcount=<value optimized out>, kws=<value optimized out>, kwcount=<value optimized out>, defs=<value optimized out>, defcount=<value optimized out>, closure=<value optimized out>) at Python/ceval.c:2736 #9 0x0000003cc244c45a in function_call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/funcobject.c:548 #10 0x0000003cc24360f0 in PyObject_Call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/abstract.c:1795 #11 0x0000003cc249352c in PyEval_EvalFrame (f=<value optimized out>) at Python/ceval.c:3840 #12 0x0000003cc2495fe5 in PyEval_EvalCodeEx (co=<value optimized out>, globals=<value optimized out>, locals=<value optimized out>, args=<value optimized out>, argcount=<value optimized out>, kws=<value optimized out>, kwcount=<value optimized out>, defs=<value optimized out>, defcount=<value optimized out>, closure=<value optimized out>) at Python/ceval.c:2736 #13 0x0000003cc249473f in PyEval_EvalFrame (f=<value optimized out>) at Python/ceval.c:3656 #14 0x0000003cc2495fe5 in PyEval_EvalCodeEx (co=<value optimized out>, globals=<value optimized out>, locals=<value optimized out>, args=<value optimized out>, argcount=<value optimized out>, kws=<value optimized out>, kwcount=<value optimized out>, defs=<value optimized out>, defcount=<value optimized out>, closure=<value optimized out>) at Python/ceval.c:2736 #15 0x0000003cc244c367 in function_call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/funcobject.c:548 #16 0x0000003cc24360f0 in PyObject_Call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/abstract.c:1795 #17 0x0000003cc243c1ef in instancemethod_call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/classobject.c:2447 #18 0x0000003cc24360f0 in PyObject_Call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/abstract.c:1795 #19 0x0000003cc248fc3d in PyEval_CallObjectWithKeywords ( func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Python/ceval.c:3430 #20 0x0000003cc243fc10 in PyInstance_New (klass=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/classobject.c:575 #21 0x0000003cc24360f0 in PyObject_Call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/abstract.c:1795 #22 0x0000003cc24928ce in PyEval_EvalFrame (f=<value optimized out>) at Python/ceval.c:3771 #23 0x0000003cc2495fe5 in PyEval_EvalCodeEx (co=<value optimized out>, globals=<value optimized out>, locals=<value optimized out>, args=<value optimized out>, argcount=<value optimized out>, kws=<value optimized out>, kwcount=<value optimized out>, defs=<value optimized out>, defcount=<value optimized out>, closure=<value optimized out>) at Python/ceval.c:2736 #24 0x0000003cc244c367 in function_call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/funcobject.c:548 #25 0x0000003cc24360f0 in PyObject_Call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/abstract.c:1795 #26 0x0000003cc243c1ef in instancemethod_call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/classobject.c:2447 #27 0x0000003cc24360f0 in PyObject_Call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/abstract.c:1795 #28 0x0000003cc248fc3d in PyEval_CallObjectWithKeywords ( func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Python/ceval.c:3430 #29 0x0000003cc243fc10 in PyInstance_New (klass=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/classobject.c:575 #30 0x0000003cc24360f0 in PyObject_Call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/abstract.c:1795 #31 0x0000003cc24928ce in PyEval_EvalFrame (f=<value optimized out>) at Python/ceval.c:3771 #32 0x0000003cc2494b66 in PyEval_EvalFrame (f=<value optimized out>) at Python/ceval.c:3645 #33 0x0000003cc2494b66 in PyEval_EvalFrame (f=<value optimized out>) at Python/ceval.c:3645 #34 0x0000003cc2495fe5 in PyEval_EvalCodeEx (co=<value optimized out>, globals=<value optimized out>, locals=<value optimized out>, args=<value optimized out>, argcount=<value optimized out>, kws=<value optimized out>, kwcount=<value optimized out>, defs=<value optimized out>, defcount=<value optimized out>, closure=<value optimized out>) at Python/ceval.c:2736 #35 0x0000003cc244c367 in function_call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/funcobject.c:548 #36 0x0000003cc24360f0 in PyObject_Call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/abstract.c:1795 #37 0x0000003cc243c1ef in instancemethod_call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/classobject.c:2447 #38 0x0000003cc24360f0 in PyObject_Call (func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Objects/abstract.c:1795 #39 0x0000003cc248fc3d in PyEval_CallObjectWithKeywords ( func=<value optimized out>, arg=<value optimized out>, kw=<value optimized out>) at Python/ceval.c:3430 #40 0x0000003cc24bbbbd in t_bootstrap (boot_raw=<value optimized out>) at Modules/threadmodule.c:434 #41 0x0000003cc1c064a7 in start_thread () from /lib64/libpthread.so.0 #42 0x0000003cc14d3c2d in clone () from /lib64/libc.so.6

On Thu, Nov 26, 2009 at 01:53:32PM +0200, Dan Kenigsberg wrote:
On Wed, Nov 25, 2009 at 12:06:03PM +0000, Daniel P. Berrange wrote:
* libvirt-override.c: Add many missing calls to allow threading when entering C code, otherwise python blocks & then deadlocks when we have an async event to dispatch back into python code
Thanks, but I am still experiencing deadlocks when I run more than one domain.
Great, you found the one remaining bug I delibrately left in ;-P I've pushed this patch together with the fix for that bug, so it really should work now. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
participants (4)
-
Dan Kenigsberg
-
Daniel P. Berrange
-
Daniel Veillard
-
Matthias Bolte