From 4b61607094dc9a9f95e4c83f72ba9a67d99519c4 Mon Sep 17 00:00:00 2001 From: tanyulong Date: Sat, 31 Jul 2021 09:56:25 +0800 Subject: [PATCH] Fix multi process contention for the DBusName in VNC environment --- src/main.cpp | 59 ++++++++++++++++++++++++++++++++++++++------ src/ukws_common.h | 4 +++ src/ukws_manager.cpp | 20 +++++++++------ 3 files changed, 69 insertions(+), 14 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ae0442f..4f02dc0 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -161,18 +162,62 @@ void msgHandler(QtMsgType type, const QMessageLogContext& context, const QString abort(); } +bool startUkws(QString serviceName) { + bool dbusIsReady = false; + + QProcess *newUkws = new QProcess(); + newUkws->setProgram("/usr/bin/ukui-window-switch"); + newUkws->setStandardOutputFile("/dev/null"); + newUkws->setStandardErrorFile("/dev/null"); + newUkws->startDetached(); + + QTime curTime = QTime::currentTime(); + curTime.start(); + + while (curTime.elapsed() < 1100) { + QDBusInterface interface(serviceName, UKWS_DBUS_PATH, UKWS_DBUS_INTERFACE, + QDBusConnection::sessionBus()); + if (!interface.isValid()) { + usleep(250 * 1000); + } else { + dbusIsReady = true; + break; + } + } + + if (dbusIsReady) { + qInfo() << "ukui-window-switch is started"; + return true; + } else { + qInfo() << "ukui-window-switch start failed"; + return false; + } + + return false; +} + void handleWorkspaceView() { - QString object = QString(getenv("DISPLAY")); - object = object.trimmed().replace(":", "_").replace(".", "_").replace("-", "_"); - object = "/org/ukui/WindowSwitch/display/" + object; - QDBusInterface interface("org.ukui.WindowSwitch", object, - "org.ukui.WindowSwitch", + // 根据当前的DISPLAY环境变量构造单独的DBus Name + QString serviceName = QString(getenv("DISPLAY")); + serviceName = serviceName.trimmed().replace(":", "_").replace(".", "_").replace("-", "_"); + if (!serviceName.isEmpty()) + serviceName = QString(UKWS_DBUS_NAME_PREFIX) + "." + serviceName; + else + serviceName = UKWS_DBUS_NAME_PREFIX; + qDebug() << "Access DBus:" << serviceName; + + QDBusInterface interface(serviceName, UKWS_DBUS_PATH, UKWS_DBUS_INTERFACE, QDBusConnection::sessionBus()); if (!interface.isValid()) { - qCritical() << QDBusConnection::sessionBus().lastError().message(); - exit(1); + qDebug() << QDBusConnection::sessionBus().lastError().message(); + qInfo() << "Try to start ukui-window-switch"; + if (!startUkws(serviceName)) { + qCritical() << "Start ukui-window-switch failed"; + exit(1); + } } + //调用远程的value方法 QDBusReply reply = interface.call("handleWorkspace"); if (reply.isValid()) { diff --git a/src/ukws_common.h b/src/ukws_common.h index f3631ef..39c660d 100755 --- a/src/ukws_common.h +++ b/src/ukws_common.h @@ -34,6 +34,10 @@ #define UKWS_OBJ_NEW_WS_TITLE "new-workspace-title" #define UKWS_OBJ_NEW_WS_LABEL "new-workspace-label" +#define UKWS_DBUS_NAME_PREFIX "org.ukui.WindowSwitch.Display" +#define UKWS_DBUS_PATH "/org/ukui/WindowSwitch" +#define UKWS_DBUS_INTERFACE "org.ukui.WindowSwitch" + enum UkwsWidgetShowStatus { Hidden = 0, Shown, diff --git a/src/ukws_manager.cpp b/src/ukws_manager.cpp index e9cffe3..ecd4f1e 100755 --- a/src/ukws_manager.cpp +++ b/src/ukws_manager.cpp @@ -92,19 +92,25 @@ UkwsManager::UkwsManager(QWidget *parent) : QWidget(parent) connect(ws, &UkwsWorkspaceManager::isHidden, this, &UkwsManager::hideWorkspace); // connect(altChecker, &UkwsAltChecker::altReleased, this, &UkwsManager::hideIndicator); + // 根据当前的DISPLAY环境变量构造单独的DBus Name + QString serviceName = QString(getenv("DISPLAY")); + serviceName = serviceName.trimmed().replace(":", "_").replace(".", "_").replace("-", "_"); + if (!serviceName.isEmpty()) + serviceName = QString(UKWS_DBUS_NAME_PREFIX) + "." + serviceName; + else + serviceName = UKWS_DBUS_NAME_PREFIX; + qDebug() << "Register DBus Name:" << serviceName; + + // 连接session总线 QDBusConnection connection = QDBusConnection::sessionBus(); // 在session总线上为UKWS注册服务 - if(!connection.registerService("org.ukui.WindowSwitch")) { + if(!connection.registerService(serviceName)) { qCritical() << "Register DBus Service Error:" << connection.lastError().message(); } - // 注册org.ukui.WindowSwitch服务的object,把UkwsManager类的所有公共槽函数导出为object的method - QString object = QString(getenv("DISPLAY")); - object = object.trimmed().replace(":", "_").replace(".", "_").replace("-", "_"); - object = "/org/ukui/WindowSwitch/display/" + object; - qDebug() << "Register DBus:" << object; - connection.registerObject(object, this, QDBusConnection::ExportAllSlots); + connection.registerObject(UKWS_DBUS_PATH, UKWS_DBUS_INTERFACE, + this, QDBusConnection::ExportAllSlots); } void UkwsManager::setConfig(UkwsConfig *config) -- 2.23.0