]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Release conn lock before reporting interface errors
authorLaine Stump <laine@laine.org>
Wed, 22 Jul 2009 14:15:52 +0000 (16:15 +0200)
committerDaniel Veillard <veillard@redhat.com>
Wed, 22 Jul 2009 14:15:52 +0000 (16:15 +0200)
* src/datatypes.c: fix a lock problem on error handling, as the
  error report takes the lock, it must be released before, fixes
  the problem but just for Interface objects

src/datatypes.c

index 0e3628abd7b45d57adba9a9875a954cf875679f6..3e528748f04f1796721269c0093158f8c6732190 100644 (file)
@@ -568,16 +568,19 @@ _("Failed to change interface mac address from %s to %s due to differing lengths
         }
     } 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 @@ _("Failed to change interface mac address from %s to %s due to differing lengths
         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 @@ _("Failed to change interface mac address from %s to %s due to differing lengths
     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);
 }