diff --git a/src/datatypes.c b/src/datatypes.c index 8b3f8c3633..d03a679a31 100644 --- a/src/datatypes.c +++ b/src/datatypes.c @@ -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); diff --git a/src/libvirt.c b/src/libvirt.c index e450ad9eca..ca8e00394d 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -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); } /**