From b88b171731b6c00cd04c7ffd79b04ccdaf9502c9 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 31 Oct 2012 19:03:57 +0000 Subject: [PATCH] Shut down session libvirtd cleanly on host shutdown/user logout 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 --- daemon/libvirtd.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index f7046f619f..91b3c116ef 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -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);