mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
Fix up connection reference counting.
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>
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user