On Wed, Nov 30, 2011 at 02:03:18PM +0100, Christophe Fergeau wrote:
On Tue, Nov 29, 2011 at 11:51:38PM +0100, Christophe Fergeau wrote:
> On Tue, Nov 29, 2011 at 05:00:54PM +0200, Zeeshan Ali (Khattak) wrote:
> > From: "Zeeshan Ali (Khattak)" <zeeshanak(a)gnome.org>
> >
> > This patch doesn't work cause virDomainIsPersistent() is returning
'1'
> > on transient domain for some reason. Send it to list to get some help.
> > ---
> > libvirt-gobject/libvirt-gobject-connection.c | 9 +++++++++
> > 1 files changed, 9 insertions(+), 0 deletions(-)
> >
> > diff --git a/libvirt-gobject/libvirt-gobject-connection.c
b/libvirt-gobject/libvirt-gobject-connection.c
> > index b647bfa..1b0259e 100644
> > --- a/libvirt-gobject/libvirt-gobject-connection.c
> > +++ b/libvirt-gobject/libvirt-gobject-connection.c
> > @@ -362,6 +362,15 @@ static int domain_event_cb(virConnectPtr conn
G_GNUC_UNUSED,
> > g_signal_emit_by_name(gdom,
"stopped::from-snapshot");
> > else
> > g_warn_if_reached();
> > +
> > + if (!virDomainIsPersistent(dom)) {
> > + g_mutex_lock(priv->lock);
> > + g_hash_table_steal(priv->domains, uuid);
> > + g_mutex_unlock(priv->lock);
> > +
> > + g_signal_emit(gconn, signals[VIR_DOMAIN_REMOVED], 0, gdom);
> > + g_object_unref(gdom);
> > + }
> > break;
>
> Not directly related to this patch since the same pattern is already
> present in domain_event_cb, but this can race with gvir_connection_close,
> ie gdom is looked up in domain_event_cb, gvir_connection_close frees
> priv->domains and its content, domain_event_cb resumes and happily uses
> gdom which it hasn't reffed and priv->domains. Something similar can also
> happen between domain_event_cb and gvir_connection_fetch_domains.
What about something like the patch below? I'll make a proper patch and
make sure it does not conflict with Zeeshan's patch if that looks like the
way to go.
Christophe
diff --git a/libvirt-gobject/libvirt-gobject-connection.c
b/libvirt-gobject/libvirt-gobject-connection.c
index c9985b2..e00c5bf 100644
--- a/libvirt-gobject/libvirt-gobject-connection.c
+++ b/libvirt-gobject/libvirt-gobject-connection.c
@@ -261,6 +261,7 @@ static int domain_event_cb(virConnectPtr conn G_GNUC_UNUSED,
GVirDomain *gdom;
GVirConnectionPrivate *priv = gconn->priv;
gboolean was_unknown = FALSE;
+ GHashTable *doms;
if (virDomainGetUUIDString(dom, uuid) < 0) {
g_warning("Failed to get domain UUID on %p", dom);
@@ -270,14 +271,17 @@ 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), gdom);
g_mutex_unlock(priv->lock);
was_unknown = TRUE;
@@ -296,11 +300,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;
@@ -372,6 +375,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;
}
Looks reasonable to me.
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 :|