diff --git a/src/kdbusservice.h b/src/kdbusservice.h --- a/src/kdbusservice.h +++ b/src/kdbusservice.h @@ -115,7 +115,17 @@ * The exit value of a @c Unique instance can be set from the running * instance with setExitValue(), the default value is @c 0. */ - NoExitOnFailure = 4 + NoExitOnFailure = 4, + /** + * Indicates that if there's already a unique service running, to be quit and replaced + * with our own. + * + * If exported, it will try first quitting the service calling org.qtproject.Qt.QCoreApplication.quit, + * which is exported by @class KDBusService by default. + * + * @since 5.62 + */ + Replace = 8 }; Q_ENUM(StartupOption) diff --git a/src/kdbusservice.cpp b/src/kdbusservice.cpp --- a/src/kdbusservice.cpp +++ b/src/kdbusservice.cpp @@ -168,7 +168,32 @@ auto queueOption = QDBusConnectionInterface::DontQueueService; - if (options & KDBusService::Unique) { + if (options & KDBusService::Replace && QDBusConnection::sessionBus().interface()->isServiceRegistered(d->serviceName)) { + auto message = QDBusMessage::createMethodCall(d->serviceName, + QStringLiteral("/MainApplication"), + QStringLiteral("org.qtproject.Qt.QCoreApplication"), + QStringLiteral("quit")); + auto reply = QDBusConnection::sessionBus().call(message); //deliberately block until it's done, so we register the name after the app quits + + //Give a grace time to the original instance + { + QEventLoop unregistrationLoop; + connect(bus, &QDBusConnectionInterface::serviceUnregistered, + this, [&unregistrationLoop, this](const QString &service) { + if (service != d->serviceName) { + return; + } + + unregistrationLoop.quit(); + }); + + QTimer quitTimer; + quitTimer.start(2000); + connect(&quitTimer, &QTimer::timeout, &unregistrationLoop, &QEventLoop::quit); + unregistrationLoop.exec(); + } + queueOption = QDBusConnectionInterface::ReplaceExistingService; + } else if (options & KDBusService::Unique) { // When a process crashes and gets auto-restarted by KCrash we may // be in this code path "too early". There is a bit of a delay // between the restart and the previous process dropping off of the