[libvirt] [PATCH] virsh: Fix possible deadlock when virsh is about to exit
by Jiri Denemark
Not only was ctl->quit accessed without a mutex but unfortunately,
virEventAddTimeout only interrupts the poll when event loop is running
so the hack needs to add a timeout that will make next poll return
immediately without blocking.
---
tools/virsh.c | 39 +++++++++++++++++++++++++++++++++------
1 files changed, 33 insertions(+), 6 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 618b0c1..723ec65 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -251,6 +251,7 @@ typedef struct __vshControl {
bool useSnapshotOld; /* cannot use virDomainSnapshotGetParent or
virDomainSnapshotNumChildren */
virThread eventLoop;
+ virMutex lock;
bool eventLoopStarted;
bool quit;
} __vshControl;
@@ -16796,10 +16797,17 @@ vshEventLoop(void *opaque)
{
vshControl *ctl = opaque;
- while (!ctl->quit) {
- if (virEventRunDefaultImpl() < 0) {
+ while (1) {
+ bool quit;
+ virMutexLock(&ctl->lock);
+ quit = ctl->quit;
+ virMutexUnlock(&ctl->lock);
+
+ if (quit)
+ break;
+
+ if (virEventRunDefaultImpl() < 0)
virshReportError(ctl);
- }
}
}
@@ -17235,13 +17243,18 @@ vshReadline (vshControl *ctl, const char *prompt)
#endif /* !USE_READLINE */
+static void
+vshDeinitTimer(int timer ATTRIBUTE_UNUSED, void *opaque ATTRIBUTE_UNUSED)
+{
+ /* nothing to be done here */
+}
+
/*
* Deinitialize virsh
*/
static bool
vshDeinit(vshControl *ctl)
{
- ctl->quit = true;
vshReadlineDeinit(ctl);
vshCloseLogFile(ctl);
VIR_FREE(ctl->name);
@@ -17254,15 +17267,24 @@ vshDeinit(vshControl *ctl)
virResetLastError();
if (ctl->eventLoopStarted) {
+ int timer;
+
+ virMutexLock(&ctl->lock);
+ ctl->quit = true;
/* HACK: Add a dummy timeout to break event loop */
- int timer = virEventAddTimeout(-1, NULL, NULL, NULL);
+ timer = virEventAddTimeout(0, vshDeinitTimer, NULL, NULL);
+ virMutexUnlock(&ctl->lock);
+
+ virThreadJoin(&ctl->eventLoop);
+
if (timer != -1)
virEventRemoveTimeout(timer);
- virThreadJoin(&ctl->eventLoop);
ctl->eventLoopStarted = false;
}
+ virMutexDestroy(&ctl->lock);
+
return true;
}
@@ -17543,6 +17565,11 @@ main(int argc, char **argv)
return EXIT_FAILURE;
}
+ if (virMutexInit(&ctl->lock) < 0) {
+ vshError(ctl, "%s", _("Failed to initialize mutex"));
+ return EXIT_FAILURE;
+ }
+
if (virInitialize() < 0) {
vshError(ctl, "%s", _("Failed to initialize libvirt"));
return EXIT_FAILURE;
--
1.7.8.rc4
12 years, 12 months
[libvirt] [PATCHv2 2/6] qemu: Plug memory leak onqemuProcessWaitForMonitor() error path
by ajia@redhat.com
From: Alex Jia <ajia(a)redhat.com>
Detected by Coverity. Leak introduced in commit 109efd7.
Signed-off-by: Alex Jia <ajia(a)redhat.com>
---
src/qemu/qemu_process.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 2563f97..b05c280 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1224,7 +1224,7 @@ qemuProcessWaitForMonitor(struct qemud_driver* driver,
if (VIR_ALLOC_N(buf, buf_size) < 0) {
virReportOOMError();
- return -1;
+ goto closelog;
}
if (qemuProcessReadLogOutput(vm, logfd, buf, buf_size,
--
1.7.1
12 years, 12 months
[libvirt] [PATCHv4 0/4] implement per-device cgroup blkio weight in qemu
by Eric Blake
v8: two new bug cleanup commits, move major()/minor() handling out of
domain_conf.c into cgroup.c, and fix behavior when more than one
device is listed, add a test for xml parsing.
v7 was here (1-3 are already applied, 4-5 of that series are now 3-4):
https://www.redhat.com/archives/libvir-list/2011-November/msg00317.html
Eric Blake (2):
API: prevent query of --live and --config at once
qemu: fix blkiotune --live --config
Hu Tao (2):
blkiotune: add interface for blkiotune.device_weight
blkiotune: add qemu support for blkiotune.device_weight
docs/formatdomain.html.in | 29 +++-
docs/schemas/domaincommon.rng | 26 ++-
include/libvirt/libvirt.h.in | 10 +
src/conf/domain_conf.c | 99 +++++++++-
src/conf/domain_conf.h | 14 ++
src/libvirt.c | 36 +++-
src/libvirt_private.syms | 2 +
src/qemu/qemu_cgroup.c | 20 ++
src/qemu/qemu_driver.c | 223 +++++++++++++++++++-
src/util/cgroup.c | 51 +++++
src/util/cgroup.h | 4 +
.../qemuxml2argv-blkiotune-device.args | 4 +
.../qemuxml2argv-blkiotune-device.xml | 36 +++
tests/qemuxml2argvtest.c | 1 +
tests/qemuxml2xmltest.c | 1 +
tools/virsh.c | 43 +++-
tools/virsh.pod | 8 +-
17 files changed, 576 insertions(+), 31 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-blkiotune-device.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-blkiotune-device.xml
--
1.7.7.1
12 years, 12 months
[libvirt] [PATCH] Fix bug on setting both weight and device-weights at the same time
by Hu Tao
When setting both blkio weight and device-weights at the same time, the weight
is lost. Fix it.
---
tools/virsh.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 01da8e5..af9f538 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -4788,14 +4788,14 @@ cmdBlkiotune(vshControl * ctl, const vshCmd * cmd)
if (!virStrcpy(temp->field, VIR_DOMAIN_BLKIO_WEIGHT,
sizeof(temp->field)))
goto cleanup;
- }
-
- if (device_weight) {
+ weight = 0;
+ } else if (device_weight) {
temp->value.s = vshStrdup(ctl, device_weight);
temp->type = VIR_TYPED_PARAM_STRING;
if (!virStrcpy(temp->field, VIR_DOMAIN_BLKIO_DEVICE_WEIGHT,
sizeof(temp->field)))
goto cleanup;
+ device_weight = NULL;
}
}
--
1.7.3.1
12 years, 12 months
[libvirt] [libvirt-glib] Fix potential race in GVirObjectConnection::domain_event_cb
by Christophe Fergeau
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;
}
--
1.7.7.3
12 years, 12 months
[libvirt] [libvirt-glib] Fix gvir_config_domain_clock_set_variable_offset
by Christophe Fergeau
It was creating an extra <clock> node as a child of the "main" one
which is not what was intended
---
libvirt-gconfig/libvirt-gconfig-domain-clock.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/libvirt-gconfig/libvirt-gconfig-domain-clock.c b/libvirt-gconfig/libvirt-gconfig-domain-clock.c
index 27d1e67..b28856c 100644
--- a/libvirt-gconfig/libvirt-gconfig-domain-clock.c
+++ b/libvirt-gconfig/libvirt-gconfig-domain-clock.c
@@ -121,7 +121,7 @@ void gvir_config_domain_clock_set_variable_offset(GVirConfigDomainClock *klock,
g_return_if_fail(GVIR_IS_CONFIG_DOMAIN_CLOCK(klock));
- node = gvir_config_object_replace_child(GVIR_CONFIG_OBJECT(klock), "clock");
+ node = gvir_config_object_get_xml_node(GVIR_CONFIG_OBJECT(klock));
if (node == NULL)
return;
--
1.7.7.3
12 years, 12 months
[libvirt] [libvirt-glib 1/2] Rely on libvirt API to detect transient domains
by Zeeshan Ali (Khattak)
From: "Zeeshan Ali (Khattak)" <zeeshanak(a)gnome.org>
---
libvirt-gobject/libvirt-gobject-connection.c | 6 +-----
1 files changed, 1 insertions(+), 5 deletions(-)
diff --git a/libvirt-gobject/libvirt-gobject-connection.c b/libvirt-gobject/libvirt-gobject-connection.c
index c9985b2..b647bfa 100644
--- a/libvirt-gobject/libvirt-gobject-connection.c
+++ b/libvirt-gobject/libvirt-gobject-connection.c
@@ -260,7 +260,6 @@ static int domain_event_cb(virConnectPtr conn G_GNUC_UNUSED,
GVirConnection *gconn = opaque;
GVirDomain *gdom;
GVirConnectionPrivate *priv = gconn->priv;
- gboolean was_unknown = FALSE;
if (virDomainGetUUIDString(dom, uuid) < 0) {
g_warning("Failed to get domain UUID on %p", dom);
@@ -279,8 +278,6 @@ static int domain_event_cb(virConnectPtr conn G_GNUC_UNUSED,
g_mutex_lock(priv->lock);
g_hash_table_insert(priv->domains, (gpointer)gvir_domain_get_uuid(gdom), gdom);
g_mutex_unlock(priv->lock);
-
- was_unknown = TRUE;
}
switch (event) {
@@ -307,8 +304,7 @@ static int domain_event_cb(virConnectPtr conn G_GNUC_UNUSED,
case VIR_DOMAIN_EVENT_STARTED:
if (detail == VIR_DOMAIN_EVENT_STARTED_BOOTED) {
- if (was_unknown)
- /* Most probably a transient domain */
+ if (!virDomainIsPersistent(dom))
g_signal_emit(gconn, signals[VIR_DOMAIN_ADDED], 0, gdom);
g_signal_emit_by_name(gdom, "started::booted");
} else if (detail == VIR_DOMAIN_EVENT_STARTED_MIGRATED)
--
1.7.7.3
12 years, 12 months
[libvirt] [libvirt-glib 01/13] Add GVirConfigXmlDoc type
by Christophe Fergeau
This class derives from GObject and wraps an xmlDocPtr. It will be
useful to refcount xmlDoc so that it can be shared between multiple
GVirConfigObject instances.
---
libvirt-gconfig/Makefile.am | 4 +-
libvirt-gconfig/libvirt-gconfig-xml-doc.c | 137 +++++++++++++++++++++++++++++
libvirt-gconfig/libvirt-gconfig-xml-doc.h | 66 ++++++++++++++
3 files changed, 206 insertions(+), 1 deletions(-)
create mode 100644 libvirt-gconfig/libvirt-gconfig-xml-doc.c
create mode 100644 libvirt-gconfig/libvirt-gconfig-xml-doc.h
diff --git a/libvirt-gconfig/Makefile.am b/libvirt-gconfig/Makefile.am
index e91c601..8276d07 100644
--- a/libvirt-gconfig/Makefile.am
+++ b/libvirt-gconfig/Makefile.am
@@ -35,6 +35,7 @@ GCONFIG_HEADER_FILES = \
noinst_HEADERS = \
libvirt-gconfig-helpers-private.h \
libvirt-gconfig-object-private.h
+ libvirt-gconfig-xml-doc.h
GCONFIG_SOURCE_FILES = \
libvirt-gconfig-object.c \
libvirt-gconfig-capabilities.c \
@@ -59,7 +60,8 @@ GCONFIG_SOURCE_FILES = \
libvirt-gconfig-node-device.c \
libvirt-gconfig-secret.c \
libvirt-gconfig-storage-pool.c \
- libvirt-gconfig-storage-vol.c
+ libvirt-gconfig-storage-vol.c \
+ libvirt-gconfig-xml-doc.c
libvirt_gconfig_1_0_ladir = $(includedir)/libvirt-gconfig-1.0/libvirt-gconfig
libvirt_gconfig_1_0_la_HEADERS = \
diff --git a/libvirt-gconfig/libvirt-gconfig-xml-doc.c b/libvirt-gconfig/libvirt-gconfig-xml-doc.c
new file mode 100644
index 0000000..7906158
--- /dev/null
+++ b/libvirt-gconfig/libvirt-gconfig-xml-doc.c
@@ -0,0 +1,137 @@
+/*
+ * libvirt-gobject-config-xml-node.c: libvirt glib integration
+ *
+ * Copyright (C) 2011 Red Hat
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Christophe Fergeau <cfergeau(a)gmail.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <libxml/tree.h>
+
+#include "libvirt-gconfig/libvirt-gconfig.h"
+#include "libvirt-gconfig/libvirt-gconfig-xml-doc.h"
+
+extern gboolean debugFlag;
+
+#define DEBUG(fmt, ...) do { if (G_UNLIKELY(debugFlag)) g_debug(fmt, ## __VA_ARGS__); } while (0)
+
+#define GVIR_CONFIG_XML_DOC_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((obj), GVIR_TYPE_CONFIG_XML_DOC, GVirConfigXmlDocPrivate))
+
+struct _GVirConfigXmlDocPrivate
+{
+ xmlDocPtr doc;
+};
+
+G_DEFINE_TYPE(GVirConfigXmlDoc, gvir_config_xml_doc, G_TYPE_OBJECT);
+
+enum {
+ PROP_0,
+ PROP_DOC
+};
+
+static void gvir_config_xml_doc_get_property(GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GVirConfigXmlDoc *xml_doc = GVIR_CONFIG_XML_DOC(object);
+
+ switch (prop_id) {
+ case PROP_DOC:
+ g_value_set_pointer(value, xml_doc->priv->doc);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+static void gvir_config_xml_doc_set_property(GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GVirConfigXmlDoc *doc = GVIR_CONFIG_XML_DOC(object);
+
+ switch (prop_id) {
+ case PROP_DOC:
+ doc->priv->doc = g_value_get_pointer(value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+static void gvir_config_xml_doc_finalize(GObject *object)
+{
+ GVirConfigXmlDoc *doc = GVIR_CONFIG_XML_DOC(object);
+ GVirConfigXmlDocPrivate *priv = doc->priv;
+
+ DEBUG("Finalize GVirConfigXmlDoc=%p", doc);
+
+ if (priv->doc)
+ xmlFreeDoc(priv->doc);
+
+ G_OBJECT_CLASS(gvir_config_xml_doc_parent_class)->finalize(object);
+}
+
+static void gvir_config_xml_doc_class_init(GVirConfigXmlDocClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+ g_type_class_add_private(klass, sizeof(GVirConfigXmlDocPrivate));
+
+ object_class->finalize = gvir_config_xml_doc_finalize;
+ object_class->get_property = gvir_config_xml_doc_get_property;
+ object_class->set_property = gvir_config_xml_doc_set_property;
+
+ g_object_class_install_property(object_class,
+ PROP_DOC,
+ g_param_spec_pointer("doc",
+ "XML Doc",
+ "The XML doc this config object corresponds to",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+}
+
+
+static void gvir_config_xml_doc_init(GVirConfigXmlDoc *xml_doc)
+{
+ GVirConfigXmlDocPrivate *priv;
+
+ DEBUG("Init GVirConfigXmlDoc=%p", xml_doc);
+
+ priv = xml_doc->priv = GVIR_CONFIG_XML_DOC_GET_PRIVATE(xml_doc);
+
+ memset(priv, 0, sizeof(*priv));
+}
+
+
+GVirConfigXmlDoc *gvir_config_xml_doc_new(xmlDocPtr doc)
+{
+ if (doc == NULL) {
+ doc = xmlNewDoc((xmlChar *)"1.0");
+ }
+ return GVIR_CONFIG_XML_DOC(g_object_new(GVIR_TYPE_CONFIG_XML_DOC,
+ "doc", doc,
+ NULL));
+}
diff --git a/libvirt-gconfig/libvirt-gconfig-xml-doc.h b/libvirt-gconfig/libvirt-gconfig-xml-doc.h
new file mode 100644
index 0000000..079de1e
--- /dev/null
+++ b/libvirt-gconfig/libvirt-gconfig-xml-doc.h
@@ -0,0 +1,66 @@
+/*
+ * libvirt-gobject-xml-doc.h: libvirt gobject integration
+ *
+ * Copyright (C) 2011 Red Hat
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Christophe Fergeau <cfergeau(a)gmail.com>
+ */
+
+#if !defined(__LIBVIRT_GCONFIG_H__) && !defined(LIBVIRT_GCONFIG_BUILD)
+#error "Only <libvirt-gconfig/libvirt-gconfig.h> can be included directly."
+#endif
+
+#ifndef __LIBVIRT_GCONFIG_XML_DOC_H__
+#define __LIBVIRT_GCONFIG_XML_DOC_H__
+
+G_BEGIN_DECLS
+
+#define GVIR_TYPE_CONFIG_XML_DOC (gvir_config_xml_doc_get_type ())
+#define GVIR_CONFIG_XML_DOC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GVIR_TYPE_CONFIG_XML_DOC, GVirConfigXmlDoc))
+#define GVIR_CONFIG_XML_DOC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GVIR_TYPE_CONFIG_XML_DOC, GVirConfigXmlDocClass))
+#define GVIR_IS_CONFIG_XML_DOC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GVIR_TYPE_CONFIG_XML_DOC))
+#define GVIR_IS_CONFIG_XML_DOC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GVIR_TYPE_CONFIG_XML_DOC))
+#define GVIR_CONFIG_XML_DOC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GVIR_TYPE_CONFIG_XML_DOC, GVirConfigXmlDocClass))
+
+typedef struct _GVirConfigXmlDoc GVirConfigXmlDoc;
+typedef struct _GVirConfigXmlDocPrivate GVirConfigXmlDocPrivate;
+typedef struct _GVirConfigXmlDocClass GVirConfigXmlDocClass;
+
+struct _GVirConfigXmlDoc
+{
+ GObject parent;
+
+ GVirConfigXmlDocPrivate *priv;
+
+ /* Do not add fields to this struct */
+};
+
+struct _GVirConfigXmlDocClass
+{
+ GObjectClass parent_class;
+
+ gpointer padding[20];
+};
+
+
+GType gvir_config_xml_doc_get_type(void);
+
+GVirConfigXmlDoc *gvir_config_xml_doc_new(xmlDocPtr doc);
+
+G_END_DECLS
+
+#endif /* __LIBVIRT_GCONFIG_XML_DOC_H__ */
--
1.7.7.3
12 years, 12 months
[libvirt] [libvirt-glib] Remove transient domain reference on shutdown
by Zeeshan Ali (Khattak)
From: "Zeeshan Ali (Khattak)" <zeeshanak(a)gnome.org>
---
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..59b828d 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) != 1) {
+ 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;
default:
--
1.7.7.3
12 years, 12 months