From: Alexander Larsson <alexl(a)redhat.com>
When the session dies or when the system is going to be shut down
we issue a virStateStop() call to instruct drivers to prepare to
be stopped. This will remove any previously acquire inhibitions.
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
daemon/libvirtd.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index b1b3ef7..40c411c 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -98,6 +98,11 @@
#include "configmake.h"
+#ifdef HAVE_DBUS
+# include <dbus/dbus.h>
+# include "virdbus.h"
+#endif
+
#if HAVE_SASL
virNetSASLContextPtr saslCtxt = NULL;
#endif
@@ -774,6 +779,65 @@ static void daemonInhibitCallback(bool inhibit, void *opaque)
}
+#ifdef HAVE_DBUS
+static DBusConnection *sessionBus;
+static DBusConnection *systemBus;
+
+static void daemonStopWorker(void *opaque)
+{
+ virNetServerPtr srv = opaque;
+
+ VIR_DEBUG("Begin stop srv=%p", srv);
+
+ ignore_value(virStateStop());
+
+ VIR_DEBUG("Completed stop srv=%p", srv);
+
+ /* Exit libvirtd cleanly */
+ virNetServerQuit(srv);
+}
+
+
+/* We do this in a thread to not block the main loop */
+static void daemonStop(virNetServerPtr srv)
+{
+ virThread thr;
+ virObjectRef(srv);
+ if (virThreadCreate(&thr, false, daemonStopWorker, srv) < 0)
+ virObjectUnref(srv);
+}
+
+
+static DBusHandlerResult handleSessionMessageFunc(DBusConnection *connection
ATTRIBUTE_UNUSED,
+ DBusMessage *message,
+ void *opaque)
+{
+ virNetServerPtr srv = opaque;
+
+ VIR_DEBUG("srv=%p", srv);
+
+ if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected"))
+ daemonStop(srv);
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusHandlerResult handleSystemMessageFunc(DBusConnection *connection
ATTRIBUTE_UNUSED,
+ DBusMessage *message,
+ void *opaque)
+{
+ virNetServerPtr srv = opaque;
+
+ VIR_DEBUG("srv=%p", srv);
+
+ if (dbus_message_is_signal(message, "org.freedesktop.login1.Manager",
"PrepareForShutdown"))
+ daemonStop(srv);
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+#endif
+
+
static void daemonRunStateInit(void *opaque)
{
virNetServerPtr srv = opaque;
@@ -792,6 +856,26 @@ static void daemonRunStateInit(void *opaque)
return;
}
+#ifdef HAVE_DBUS
+ /* Tie the non-priviledged libvirtd to the session/shutdown lifecycle */
+ if (!virNetServerIsPrivileged(srv)) {
+
+ sessionBus = virDBusGetSessionBus();
+ if (sessionBus != NULL)
+ dbus_connection_add_filter(sessionBus,
+ handleSessionMessageFunc, srv, NULL);
+
+ systemBus = virDBusGetSystemBus();
+ if (systemBus != NULL) {
+ dbus_connection_add_filter(systemBus,
+ handleSystemMessageFunc, srv, NULL);
+ dbus_bus_add_match(systemBus,
+
"type='signal',sender='org.freedesktop.login1',
interface='org.freedesktop.login1.Manager'",
+ NULL);
+ }
+ }
+#endif
+
/* Only now accept clients from network */
virNetServerUpdateServices(srv, true);
virObjectUnref(srv);
--
1.7.12.1