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);
return ret;
failed:
- if (ret->driver) ret->driver->close (ret);
-
/* Ensure a global error is set in case driver forgot */
virSetGlobalError();
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);
}
/**