[libvirt] [PATCH 10/10] Shut down session libvirtd cleanly on host shutdown/user logout

Daniel P. Berrange berrange at redhat.com
Tue Nov 27 18:18:20 UTC 2012


From: Alexander Larsson <alexl at 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 at redhat.com>
---
 daemon/libvirtd.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index f7046f6..4fc065c 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.11.7




More information about the libvir-list mailing list