Since virRaiseErrorFull needs to lock the conn, we must take care to
call it with the lock *not* held.
If this patch is approved, similar patches need to be done for other
types in datatypes.c
---
src/datatypes.c | 29 +++++++++++++++++++----------
1 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/src/datatypes.c b/src/datatypes.c
index 000fa66..ba5401d 100644
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -568,16 +568,19 @@ virGetInterface(virConnectPtr conn, const char *name, const char
*mac) {
}
} else {
if (VIR_ALLOC(ret) < 0) {
+ virMutexUnlock(&conn->lock);
virReportOOMError(conn);
goto error;
}
ret->name = strdup(name);
if (ret->name == NULL) {
+ virMutexUnlock(&conn->lock);
virReportOOMError(conn);
goto error;
}
ret->mac = strdup(mac);
if (ret->mac == NULL) {
+ virMutexUnlock(&conn->lock);
virReportOOMError(conn);
goto error;
}
@@ -586,6 +589,7 @@ virGetInterface(virConnectPtr conn, const char *name, const char *mac)
{
ret->conn = conn;
if (virHashAddEntry(conn->interfaces, name, ret) < 0) {
+ virMutexUnlock(&conn->lock);
virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
_("failed to add interface to connection hash
table"));
goto error;
@@ -597,7 +601,6 @@ virGetInterface(virConnectPtr conn, const char *name, const char *mac)
{
return(ret);
error:
- virMutexUnlock(&conn->lock);
if (ret != NULL) {
VIR_FREE(ret->name);
VIR_FREE(ret->mac);
@@ -623,24 +626,30 @@ virReleaseInterface(virInterfacePtr iface) {
virConnectPtr conn = iface->conn;
DEBUG("release interface %p %s", iface, iface->name);
- if (virHashRemoveEntry(conn->interfaces, iface->name, NULL) < 0)
+ if (virHashRemoveEntry(conn->interfaces, iface->name, NULL) < 0) {
+ /* unlock before reporting error because error report grabs lock */
+ virMutexUnlock(&conn->lock);
virLibConnError(conn, VIR_ERR_INTERNAL_ERROR,
_("interface missing from connection hash table"));
+ /* don't decr the conn refct if we weren't connected to it */
+ conn = NULL;
+ }
iface->magic = -1;
VIR_FREE(iface->name);
VIR_FREE(iface->mac);
VIR_FREE(iface);
- DEBUG("unref connection %p %d", conn, conn->refs);
- conn->refs--;
- if (conn->refs == 0) {
- virReleaseConnect(conn);
- /* Already unlocked mutex */
- return;
+ if (conn) {
+ DEBUG("unref connection %p %d", conn, conn->refs);
+ conn->refs--;
+ if (conn->refs == 0) {
+ virReleaseConnect(conn);
+ /* Already unlocked mutex */
+ return;
+ }
+ virMutexUnlock(&conn->lock);
}
-
- virMutexUnlock(&conn->lock);
}
--
1.6.0.6