[libvirt] [libvirt-glib] Fix potential race in GVirObjectConnection::domain_event_cb

Daniel P. Berrange berrange at redhat.com
Wed Nov 30 13:55:25 UTC 2011


On Wed, Nov 30, 2011 at 02:51:06PM +0100, Christophe Fergeau wrote:
> This method starts by looking up a domain in priv->domains, and later,
> depending on the kind of event that occurred, it may remove this
> domain from priv->domains. While the individual operations (lookup,
> removal) are protected by priv->lock, there is no guarantee that the
> looked up domain and even priv->domains will stay unchanged when
> priv->lock isn't held.
> 
> In particular, gvir_connection_close will destroy priv->domains which
> will unreference all the domains it contains (potentially destroying
> them too), and gvir_connection_fetch_domains will change priv->domains
> value.
> 
> To avoid these issues, this commit takes a reference on priv->domains
> so that it doesn't get away behind our back, and it takes a reference
> on the looked up domain too to ensure it stays alive for the duration
> of domain_event_cb run.
> ---
>  libvirt-gobject/libvirt-gobject-connection.c |   17 +++++++++++------
>  1 files changed, 11 insertions(+), 6 deletions(-)
> 
> diff --git a/libvirt-gobject/libvirt-gobject-connection.c b/libvirt-gobject/libvirt-gobject-connection.c
> index 59b828d..786a026 100644
> --- a/libvirt-gobject/libvirt-gobject-connection.c
> +++ b/libvirt-gobject/libvirt-gobject-connection.c
> @@ -257,6 +257,7 @@ static int domain_event_cb(virConnectPtr conn G_GNUC_UNUSED,
>                             void *opaque)
>  {
>      gchar uuid[VIR_UUID_STRING_BUFLEN];
> +    GHashTable *doms;
>      GVirConnection *gconn = opaque;
>      GVirDomain *gdom;
>      GVirConnectionPrivate *priv = gconn->priv;
> @@ -269,14 +270,18 @@ static int domain_event_cb(virConnectPtr conn G_GNUC_UNUSED,
>      g_debug("%s: %s event:%d, detail:%d", G_STRFUNC, uuid, event, detail);
>  
>      g_mutex_lock(priv->lock);
> -    gdom = g_hash_table_lookup(priv->domains, uuid);
> +    doms = g_hash_table_ref(priv->domains);
> +    gdom = g_hash_table_lookup(doms, uuid);
> +    if (gdom != NULL)
> +        g_object_ref(G_OBJECT(gdom));
>      g_mutex_unlock(priv->lock);
>  
>      if (gdom == NULL) {
>          gdom = GVIR_DOMAIN(g_object_new(GVIR_TYPE_DOMAIN, "handle", dom, NULL));
>  
>          g_mutex_lock(priv->lock);
> -        g_hash_table_insert(priv->domains, (gpointer)gvir_domain_get_uuid(gdom), gdom);
> +        g_hash_table_insert(doms, (gpointer)gvir_domain_get_uuid(gdom),
> +                            g_object_ref(G_OBJECT(gdom)));
>          g_mutex_unlock(priv->lock);
>      }
>  
> @@ -293,11 +298,10 @@ static int domain_event_cb(virConnectPtr conn G_GNUC_UNUSED,
>          case VIR_DOMAIN_EVENT_UNDEFINED:
>              if (detail == VIR_DOMAIN_EVENT_UNDEFINED_REMOVED) {
>                  g_mutex_lock(priv->lock);
> -                g_hash_table_steal(priv->domains, uuid);
> +                g_hash_table_remove(doms, uuid);
>                  g_mutex_unlock(priv->lock);
>  
>                  g_signal_emit(gconn, signals[VIR_DOMAIN_REMOVED], 0, gdom);
> -                g_object_unref(gdom);
>              } else
>                  g_warn_if_reached();
>              break;
> @@ -365,11 +369,10 @@ static int domain_event_cb(virConnectPtr conn G_GNUC_UNUSED,
>  
>              if (virDomainIsPersistent(dom) != 1) {
>                  g_mutex_lock(priv->lock);
> -                g_hash_table_steal(priv->domains, uuid);
> +                g_hash_table_remove(doms, uuid);
>                  g_mutex_unlock(priv->lock);
>  
>                  g_signal_emit(gconn, signals[VIR_DOMAIN_REMOVED], 0, gdom);
> -                g_object_unref(gdom);
>              }
>              break;
>  
> @@ -377,6 +380,8 @@ static int domain_event_cb(virConnectPtr conn G_GNUC_UNUSED,
>              g_warn_if_reached();
>      }
>  
> +    g_object_unref(G_OBJECT(gdom));
> +    g_hash_table_unref(doms);
>      return 0;
>  }

ACK

Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|




More information about the libvir-list mailing list