]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Shut down session libvirtd cleanly on host shutdown/user logout
authorAlexander Larsson <alexl@redhat.com>
Wed, 31 Oct 2012 19:03:57 +0000 (19:03 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Tue, 4 Dec 2012 12:14:04 +0000 (12:14 +0000)
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@redhat.com>
daemon/libvirtd.c

index f7046f619f6f1f2419caed62d9d7647e43afa110..91b3c116ef28c91c3fc53009039f2c9460a66c96 100644 (file)
@@ -98,6 +98,8 @@
 
 #include "configmake.h"
 
+#include "virdbus.h"
+
 #if HAVE_SASL
 virNetSASLContextPtr saslCtxt = NULL;
 #endif
@@ -774,6 +776,72 @@ 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 +860,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);