Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 18 additions & 40 deletions application/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,27 +54,6 @@ QAccessibleInterface *accessibleFactory(const QString &classname, QObject *objec
return interface;
}

/**
* @brief 执行外部命令
* @param strCmd:外部命令字符串
* @param outPut:命令控制台输出
* @param error:错误信息
* @return exitcode:退出码
*/
int executCmd(const QString &strCmd, QString &outPut, QString &error)
{
QProcess proc;
proc.start(strCmd);
proc.waitForFinished(-1);
outPut = proc.readAllStandardOutput();
error = proc.readAllStandardError();
error = proc.errorString();
int exitcode = proc.exitCode();
proc.close();
return exitcode;

}

int main(int argc, char *argv[])
{
// signal(SIGINT, SIG_IGN);
Expand Down Expand Up @@ -119,32 +98,31 @@ int main(int argc, char *argv[])
// exit(0);
// }
if (a.setSingleInstance(appName)) {
QProcess proc;
QString cmd, oldPid, newPid, error;
//先判断后台服务进程是否存在,如果存在可能是强制退出导致,应先退出后台程序再重新启动磁盘管理器
cmd = QString("pidof deepin-diskmanager-service");
// 使用 QDBusInterface 调用 org.freedesktop.DBus.GetNameOwner 获取服务 owner
QDBusInterface dbusInterface("org.freedesktop.DBus",
"/org/freedesktop/DBus",
"org.freedesktop.DBus",
QDBusConnection::systemBus());
const QString serviceName = "com.deepin.diskmanager";

if (!executCmd(cmd, oldPid, error)) {
proc.startDetached("/usr/bin/dbus-send --system --type=method_call --dest=com.deepin.diskmanager /com/deepin/diskmanager com.deepin.diskmanager.Quit");
}
// 启动服务前,获取后台服务的旧 dbus owner
QDBusReply<QString> oldReply = dbusInterface.call("GetNameOwner", serviceName);
const QString oldDbusOwner = oldReply.isValid() ? oldReply.value() : QString();

QStringList argList;
argList << QDBusConnection::systemBus().baseService();
qDebug() << "Starting deepin-diskmanager-authenticateProxy with args:" << argList;
proc.startDetached("deepin-diskmanager-authenticateProxy", argList);
QProcess::startDetached("deepin-diskmanager-authenticateProxy", { QDBusConnection::systemBus().baseService() });

//正常启动程序后,循环查询后台服务是否已经启动,如果后台服务启动说明鉴权成功,启动前端界面
// 启动服务后,循环查询后台服务是否已经启动
// 当获取新 dbus owner 成功且不等于旧 dbus owner, 则认为新服务启动完成
while (1) {
cmd = QString("pidof deepin-diskmanager-service");

if (!executCmd(cmd, newPid, error) && oldPid != newPid) {
break;
QDBusReply<QString> newReply = dbusInterface.call("GetNameOwner", serviceName);
if (newReply.isValid()) {
const QString newDbusOwner = newReply.value();
if (!newDbusOwner.isEmpty() && newDbusOwner != oldDbusOwner) {
break;
}
}
QThread::msleep(300);
}

proc.close();

} else {
exit(0);
}
Expand Down
4 changes: 3 additions & 1 deletion service/diskmanagerservice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ void DiskManagerService::initConnection()

void DiskManagerService::Quit()
{
// 不鉴权, 前端启动时会调用该接口来关闭已有服务
if (!checkAuthorization())
return;

qDebug() << "DiskManagerService::Quit called";
m_partedcore->delTempMountFile();
QCoreApplication::exit(0);
Expand Down
62 changes: 60 additions & 2 deletions service/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,61 @@
#include "watcher.h"

#include <QCoreApplication>
#include <DLog>

Check warning on line 10 in service/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <DLog> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 10 in service/main.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <DLog> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QDBusConnection>

Check warning on line 11 in service/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDBusConnection> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 11 in service/main.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <QDBusConnection> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QDBusError>

Check warning on line 12 in service/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDBusError> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 12 in service/main.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <QDBusError> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QDBusInterface>

Check warning on line 13 in service/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDBusInterface> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 13 in service/main.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <QDBusInterface> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QDBusPendingCall>

Check warning on line 14 in service/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDBusPendingCall> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 14 in service/main.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <QDBusPendingCall> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QThread>

Check warning on line 15 in service/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QThread> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 15 in service/main.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <QThread> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <unistd.h>

Check warning on line 16 in service/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <unistd.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 16 in service/main.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <unistd.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

const QString DiskManagerServiceName = "com.deepin.diskmanager";
const QString DiskManagerPath = "/com/deepin/diskmanager";

/**
* @brief 尝试停止已存在的 D-Bus 服务
* @param systemBus D-Bus 连接
* @return true 表示成功停止并可重新注册,false 表示失败
*
* 通过 D-Bus 调用 Quit() 方法优雅退出,未使用 PID kill,
* 以避免 TOCTOU 竞态条件和 PID 复用带来的安全风险。
* Quit() 调用后轮询等待 D-Bus 服务名称释放,确认服务已退出。
*/
static bool stopExistingService(QDBusConnection &systemBus)
{
QDBusInterface existingService(DiskManagerServiceName, DiskManagerPath, "", systemBus);
if (!existingService.isValid()) {
qWarning() << "Cannot access existing service via D-Bus interface,"
<< "service may have already exited, retry registration";
return true;
}

qDebug() << "Calling Quit() on existing service...";
QDBusPendingCall pendingCall = existingService.asyncCall("Quit");
pendingCall.waitForFinished();
if (pendingCall.isError()) {
qWarning() << "Quit() call failed:" << pendingCall.error().message();
return false;
}

// 轮询等待 D-Bus 服务名称释放,最多等待 3 秒
qDebug() << "Quit() called successfully, waiting for service to exit...";
const int maxWaitMs = 3000;
const int pollIntervalMs = 200;
for (int elapsed = 0; elapsed < maxWaitMs; elapsed += pollIntervalMs) {
usleep(pollIntervalMs * 1000);
// 通过尝试注册来判断名称是否已释放(注册后立即释放)
if (systemBus.registerService(DiskManagerServiceName)) {
systemBus.unregisterService(DiskManagerServiceName);
qDebug() << "Service name released after" << (elapsed + pollIntervalMs) << "ms";
return true;
}
}

qWarning() << "Timed out waiting for existing service to exit";
return false;
}

int main(int argc, char *argv[])
{
//set env otherwise utils excutecmd excute command failed
Expand Down Expand Up @@ -62,15 +109,26 @@
QDBusConnection systemBus = QDBusConnection::systemBus();
if (!systemBus.registerService(DiskManagerServiceName)) {
qCritical() << "registerService failed:" << systemBus.lastError();
exit(0x0001);
// 服务名注册失败,通常是因为已有实例持有该名称,尝试停止它
if (stopExistingService(systemBus)) {
qDebug() << "Retrying registerService after stopping existing service...";
// 停止旧服务后重试注册
if (!systemBus.registerService(DiskManagerServiceName)) {
qCritical() << "registerService failed even after stopping existing service";
exit(0x0001);
}
} else {
qCritical() << "Failed to stop existing service";
exit(0x0001);
}
}
DiskManager::DiskManagerService service(frontEndDBusName);
qDebug() << "systemBus.registerService success" /*<< Dtk::Core::DLogManager::getlogFilePath()*/;
if (!systemBus.registerObject(DiskManagerPath,
&service,
QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals)) {
qCritical() << "registerObject failed:" << systemBus.lastError();
exit(0x0002);
exit(0x0002);
}

/*
Expand Down
Loading