[libvirt] [PATCH] Fix up connection reference counting.

Daniel P. Berrange berrange at redhat.com
Mon Aug 17 19:00:11 UTC 2009


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 at redhat.com>
> ---
>  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 :|




More information about the libvir-list mailing list