On Mon, Aug 17, 2009 at 12:57:17PM +0200, Chris Lalancette wrote: > 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 > > Signed-off-by: Chris Lalancette <clalance@xxxxxxxxxx> > --- > src/datatypes.c | 19 +++++++++++++++++++ > src/libvirt.c | 14 +------------- > 2 files changed, 20 insertions(+), 13 deletions(-) > > diff --git a/src/datatypes.c b/src/datatypes.c > index 9d556c8..bcb5fd4 100644 > --- a/src/datatypes.c > +++ b/src/datatypes.c > @@ -237,6 +237,25 @@ 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); > + 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 5aa7f83..472c19b 100644 > --- a/src/libvirt.c > +++ b/src/libvirt.c > @@ -1231,19 +1231,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); > } > > /** ACK Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list