]> xenbits.xensource.com Git - libvirt.git/commitdiff
Fix up connection reference counting.
authorChris Lalancette <clalance@redhat.com>
Tue, 11 Aug 2009 13:48:59 +0000 (15:48 +0200)
committerChris Lalancette <clalance@redhat.com>
Tue, 18 Aug 2009 07:26:26 +0000 (09:26 +0200)
Currently the reference counting for connections is busted.  I
first noticed it while trying to use virConnectRef; it would
eventually cause a crash in the remote_internal driver, although
that was really just a victim.  Really, we should only call the
close callbacks on the methods when the references drop to 0.  To
accomplish this, move all of the close callbacks into
virUnrefConnect (since there are lots of internal users of that
function), and arrange for virConnectClose to call that.

V2: Make sure to drop the connection lock before we call the close
    callbacks, otherwise we could deadlock the daemon
V3: Fix up a crash when we got an error from one of the drivers

Signed-off-by: Chris Lalancette <clalance@redhat.com>
src/datatypes.c
src/libvirt.c

index 8b3f8c3633649c8e689f2916e8d900a76f06d29e..d03a679a31c8942d793579a9c1a4dd1a03914eac 100644 (file)
@@ -233,6 +233,26 @@ virUnrefConnect(virConnectPtr conn) {
     conn->refs--;
     refs = conn->refs;
     if (refs == 0) {
+        /* make sure to release the connection lock before we call the
+         * close() callbacks, otherwise we will deadlock if an error
+         * is raised by any of the callbacks
+         */
+        virMutexUnlock(&conn->lock);
+        if (conn->networkDriver)
+            conn->networkDriver->close (conn);
+        if (conn->interfaceDriver)
+            conn->interfaceDriver->close (conn);
+        if (conn->storageDriver)
+            conn->storageDriver->close (conn);
+        if (conn->deviceMonitor)
+            conn->deviceMonitor->close (conn);
+        if (conn->driver)
+            conn->driver->close (conn);
+
+        /* reacquire the connection lock since virReleaseConnect expects
+         * it to already be held
+         */
+        virMutexLock(&conn->lock);
         virReleaseConnect(conn);
         /* Already unlocked mutex */
         return (0);
index e450ad9eca185c5166ee1ec661ef0824cca9d8e1..ca8e00394d8117615ef72b85860919252d613d31 100644 (file)
@@ -1099,8 +1099,6 @@ do_open (const char *name,
     return ret;
 
 failed:
-    if (ret->driver) ret->driver->close (ret);
-
     /* Ensure a global error is set in case driver forgot */
     virSetGlobalError();
 
@@ -1221,19 +1219,7 @@ virConnectClose(virConnectPtr conn)
         return (-1);
     }
 
-    if (conn->networkDriver)
-        conn->networkDriver->close (conn);
-    if (conn->interfaceDriver)
-        conn->interfaceDriver->close (conn);
-    if (conn->storageDriver)
-        conn->storageDriver->close (conn);
-    if (conn->deviceMonitor)
-        conn->deviceMonitor->close (conn);
-    conn->driver->close (conn);
-
-    if (virUnrefConnect(conn) < 0)
-        return (-1);
-    return (0);
+    return virUnrefConnect(conn);
 }
 
 /**