[libvirt] [PATCH 3/4] Release conn lock before reporting errors in vir(Get|Release)Interface

Laine Stump laine at laine.org
Wed Jul 22 05:20:58 UTC 2009


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




More information about the libvir-list mailing list