diff --git a/ksmserver/CMakeLists.txt b/ksmserver/CMakeLists.txt --- a/ksmserver/CMakeLists.txt +++ b/ksmserver/CMakeLists.txt @@ -30,7 +30,7 @@ qt5_add_dbus_interface( ksmserver_KDEINIT_SRCS ${klauncher_xml} klauncher_interface ) qt5_add_dbus_interface( ksmserver_KDEINIT_SRCS ../startkde/plasma-session/org.kde.Startup.xml startup_interface ) -qt5_add_dbus_interface( ksmserver_KDEINIT_SRCS ../startkde/plasma-session/org.kde.Shutdown.xml shutdown_interface ) +qt5_add_dbus_interface( ksmserver_KDEINIT_SRCS ../startkde/plasma-shutdown/org.kde.Shutdown.xml shutdown_interface ) kf5_add_kdeinit_executable( ksmserver ${ksmserver_KDEINIT_SRCS}) diff --git a/libkworkspace/CMakeLists.txt b/libkworkspace/CMakeLists.txt --- a/libkworkspace/CMakeLists.txt +++ b/libkworkspace/CMakeLists.txt @@ -18,7 +18,7 @@ qt5_add_dbus_interface(kworkspace_LIB_SRCS ${KSCREENLOCKER_DBUS_INTERFACES_DIR}/org.kde.screensaver.xml kscreenlocker_interface ) qt5_add_dbus_interface(kworkspace_LIB_SRCS ${plasma-workspace_SOURCE_DIR}/ksmserver/org.kde.LogoutPrompt.xml logoutprompt_interface) qt5_add_dbus_interface(kworkspace_LIB_SRCS ${plasma-workspace_SOURCE_DIR}/startkde/plasma-session/org.kde.Startup.xml startup_interface) -qt5_add_dbus_interface(kworkspace_LIB_SRCS ${plasma-workspace_SOURCE_DIR}/startkde/plasma-session/org.kde.Shutdown.xml shutdown_interface) +qt5_add_dbus_interface(kworkspace_LIB_SRCS ${plasma-workspace_SOURCE_DIR}/startkde/plasma-shutdown/org.kde.Shutdown.xml shutdown_interface) set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/org.freedesktop.login1.Manager.xml" "${CMAKE_SOURCE_DIR}/data/interfaces/org.freedesktop.login1.Seat.xml" diff --git a/startkde/CMakeLists.txt b/startkde/CMakeLists.txt --- a/startkde/CMakeLists.txt +++ b/startkde/CMakeLists.txt @@ -23,6 +23,7 @@ target_link_libraries(startplasma-wayland PRIVATE Qt5::Core Qt5::DBus KF5::ConfigCore) target_link_libraries(startplasma-waylandsession PRIVATE Qt5::Core Qt5::DBus KF5::ConfigCore) add_subdirectory(plasma-session) +add_subdirectory(plasma-shutdown) #FIXME: reconsider, looks fishy if(NOT CMAKE_INSTALL_PREFIX STREQUAL "/usr") diff --git a/startkde/plasma-session/CMakeLists.txt b/startkde/plasma-session/CMakeLists.txt --- a/startkde/plasma-session/CMakeLists.txt +++ b/startkde/plasma-session/CMakeLists.txt @@ -4,14 +4,11 @@ main.cpp autostart.cpp startup.cpp - shutdown.cpp ) ecm_qt_declare_logging_category(plasma_session_SRCS HEADER debug.h IDENTIFIER PLASMA_SESSION CATEGORY_NAME org.kde.plasma.session) qt5_add_dbus_adaptor( plasma_session_SRCS org.kde.Startup.xml startup.h Startup) -qt5_add_dbus_adaptor( plasma_session_SRCS org.kde.Shutdown.xml shutdown.h Shutdown) -qt5_add_dbus_interface( plasma_session_SRCS org.kde.Shutdown.xml shutdown_interface) set(kcminit_adaptor ${plasma-workspace_SOURCE_DIR}/startkde/kcminit/main.h) set(kcminit_xml ${CMAKE_CURRENT_BINARY_DIR}/org.kde.KCMinit.xml) diff --git a/startkde/plasma-session/main.cpp b/startkde/plasma-session/main.cpp --- a/startkde/plasma-session/main.cpp +++ b/startkde/plasma-session/main.cpp @@ -17,7 +17,6 @@ */ #include "startup.h" -#include "shutdown.h" #include @@ -30,7 +29,5 @@ app.setQuitLockEnabled(false); new Startup(&app); - new Shutdown(&app); - app.exec(); } diff --git a/startkde/plasma-session/startup.cpp b/startkde/plasma-session/startup.cpp --- a/startkde/plasma-session/startup.cpp +++ b/startkde/plasma-session/startup.cpp @@ -250,6 +250,7 @@ { qCDebug(PLASMA_SESSION) << "Finished"; upAndRunning(QStringLiteral("ready")); + qApp->quit(); } void Startup::updateLaunchEnv(const QString &key, const QString &value) diff --git a/startkde/plasma-shutdown/CMakeLists.txt b/startkde/plasma-shutdown/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/startkde/plasma-shutdown/CMakeLists.txt @@ -0,0 +1,23 @@ +set(plasma_shutdown_SRCS + main.cpp + shutdown.cpp +) + +ecm_qt_declare_logging_category(plasma_shutdown_SRCS HEADER debug.h IDENTIFIER PLASMA_SESSION CATEGORY_NAME org.kde.plasma.shutdown) + +qt5_add_dbus_adaptor(plasma_shutdown_SRCS org.kde.Shutdown.xml shutdown.h Shutdown) +qt5_add_dbus_interface(plasma_shutdown_SRCS org.kde.Shutdown.xml shutdown_interface) +qt5_add_dbus_interface( plasma_shutdown_SRCS ../../ksmserver/org.kde.KSMServerInterface.xml ksmserver_interface ) + +add_executable(plasma-shutdown ${plasma_shutdown_SRCS}) + +target_link_libraries(plasma-shutdown + Qt5::Core + Qt5::DBus + KF5::ConfigCore + PW::KWorkspace +) + +kdbusaddons_generate_dbus_service_file(plasma-shutdown org.kde.Shutdown ${KDE_INSTALL_FULL_BINDIR}) +install(TARGETS plasma-shutdown ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) + diff --git a/startkde/plasma-session/main.cpp b/startkde/plasma-shutdown/main.cpp copy from startkde/plasma-session/main.cpp copy to startkde/plasma-shutdown/main.cpp --- a/startkde/plasma-session/main.cpp +++ b/startkde/plasma-shutdown/main.cpp @@ -16,21 +16,13 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "startup.h" #include "shutdown.h" #include int main(int argc, char **argv) { QCoreApplication app(argc, argv); - - // This is needed with KJobs in a QCoreApplication as when they finish - // the internal QEventLoopLocker expires and our app exits - app.setQuitLockEnabled(false); - - new Startup(&app); new Shutdown(&app); - app.exec(); } diff --git a/startkde/plasma-session/org.kde.Shutdown.xml b/startkde/plasma-shutdown/org.kde.Shutdown.xml rename from startkde/plasma-session/org.kde.Shutdown.xml rename to startkde/plasma-shutdown/org.kde.Shutdown.xml diff --git a/startkde/plasma-session/shutdown.h b/startkde/plasma-shutdown/shutdown.h rename from startkde/plasma-session/shutdown.h rename to startkde/plasma-shutdown/shutdown.h diff --git a/startkde/plasma-session/shutdown.cpp b/startkde/plasma-shutdown/shutdown.cpp rename from startkde/plasma-session/shutdown.cpp rename to startkde/plasma-shutdown/shutdown.cpp --- a/startkde/plasma-session/shutdown.cpp +++ b/startkde/plasma-shutdown/shutdown.cpp @@ -47,7 +47,8 @@ connect(watcher, &QDBusPendingCallWatcher::finished, this, [closeSessionReply, watcher, this]() { watcher->deleteLater(); if (closeSessionReply.isError()) { - qDebug() << "ksmserver failed to complete logout"; + qCWarning(PLASMA_SESSION) << "ksmserver failed to complete logout"; + qApp->quit(); } if (closeSessionReply.value()) { logoutComplete(); @@ -60,6 +61,7 @@ void Shutdown::logoutCancelled() { m_shutdownType = KWorkSpace::ShutdownTypeNone; + qApp->quit(); } void Shutdown::logoutComplete() { diff --git a/startkde/startplasma-wayland.cpp b/startkde/startplasma-wayland.cpp --- a/startkde/startplasma-wayland.cpp +++ b/startkde/startplasma-wayland.cpp @@ -25,6 +25,7 @@ int main(int argc, char** argv) { + QCoreApplication app(argc, argv); createConfigDirectory(); setupCursor(true); diff --git a/startkde/startplasma-x11.cpp b/startkde/startplasma-x11.cpp --- a/startkde/startplasma-x11.cpp +++ b/startkde/startplasma-x11.cpp @@ -29,12 +29,14 @@ out << "GOT SIGHUP\n"; } -int main(int /*argc*/, char** /*argv*/) +int main(int argc, char** argv) { // When the X server dies we get a HUP signal from xinit. We must ignore it // because we still need to do some cleanup. signal(SIGHUP, sighupHandler); + QCoreApplication app(argc, argv); + // Boot sequence: // // kdeinit is used to fork off processes which improves memory usage diff --git a/startkde/startplasma.cpp b/startkde/startplasma.cpp --- a/startkde/startplasma.cpp +++ b/startkde/startplasma.cpp @@ -21,7 +21,11 @@ #include #include #include +#include + #include +#include + #include #include @@ -357,14 +361,41 @@ } } - const auto exitCode = runSync(QStringLiteral(CMAKE_INSTALL_FULL_BINDIR "/plasma_session"), plasmaSessionOptions); + bool rc = true; + QEventLoop e; + + QProcess startPlasmaSession; + QDBusServiceWatcher serviceWatcher; + serviceWatcher.setConnection(QDBusConnection::sessionBus()); + + // We want to exit when both ksmserver and plasma-session-shutdown have finished + // This also closes if ksmserver crashes unexpectedly, as in those cases plasma-shutdown is not running + serviceWatcher.addWatchedService(QStringLiteral("org.kde.ksmserver")); + serviceWatcher.addWatchedService(QStringLiteral("org.kde.shutdown")); + serviceWatcher.setWatchMode(QDBusServiceWatcher::WatchForUnregistration); + + QObject::connect(&startPlasmaSession, QOverload::of(&QProcess::finished), [&rc, &e](int exitCode, QProcess::ExitStatus) { + if (exitCode == 255) { + // Startup error + messageBox(QStringLiteral("startkde: Could not start ksmserver. Check your installation.\n")); + rc = false; + e.quit(); + } + }); + + QObject::connect(&serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, [&]() { + const QStringList watchedServices = serviceWatcher.watchedServices(); + bool plasmaSessionRunning = std::any_of(watchedServices.constBegin(), watchedServices.constEnd(), [](const QString &service) { + return QDBusConnection::sessionBus().interface()->isServiceRegistered(service); + }); + if (!plasmaSessionRunning) { + e.quit(); + } + }); - if (exitCode == 255) { - // Startup error - messageBox(QStringLiteral("startkde: Could not start ksmserver. Check your installation.\n")); - return false; - } - return true; + startPlasmaSession.start(QStringLiteral(CMAKE_INSTALL_FULL_BINDIR "/plasma_session"), plasmaSessionOptions); + e.exec(); + return rc; } void waitForKonqi()