From dc617910fbd1a2f9f463c08f9231fb2ed12e88c1 Mon Sep 17 00:00:00 2001 From: black-desk Date: Sat, 22 Apr 2023 17:29:10 +0800 Subject: [PATCH] fix GIO_LAUNCHED_DESKTOP_FILE_PID (#30) * fix: set GIO_LAUNCHED_DESKTOP_FILE_PID To set GIO_LAUNCHED_DESKTOP_FILE_PID, we have to manually fork and exec, as QT determined the environ use to execvp, before running childModifyer. After use bare fork and exec, we have to wait for dead child processes. Otherwise there will be zombies. Signed-off-by: black-desk * fix: X-Deepin-CreatedBy is key not value - Signed-off-by: black-desk --------- Signed-off-by: black-desk --- src/modules/launcher/launcher.cpp | 4 +- src/modules/startmanager/startmanager.cpp | 83 ++++++++++++++++------- src/modules/startmanager/startmanager.h | 1 + 3 files changed, 61 insertions(+), 27 deletions(-) diff --git a/src/modules/launcher/launcher.cpp b/src/modules/launcher/launcher.cpp index 4a4b065..6f3e757 100644 --- a/src/modules/launcher/launcher.cpp +++ b/src/modules/launcher/launcher.cpp @@ -247,8 +247,8 @@ bool Launcher::requestSendToDesktop(QString appId) // 创建桌面快捷方式文件 DesktopInfo dinfo(itemsMap[appId].info.path.toStdString()); - dinfo.getDesktopFile()->setKey(MainSection, dbusService.toStdString(), "X-Deepin-CreatedBy"); - dinfo.getDesktopFile()->setKey(MainSection, appId.toStdString(), "X-Deepin-AppID"); + dinfo.getDesktopFile()->setKey(MainSection, "X-Deepin-CreatedBy", dbusService.toStdString()); + dinfo.getDesktopFile()->setKey(MainSection, "X-Deepin-AppID", appId.toStdString()); if (!dinfo.getDesktopFile()->saveToFile(filePath.toStdString())) return false; diff --git a/src/modules/startmanager/startmanager.cpp b/src/modules/startmanager/startmanager.cpp index 4b4a2a8..b7790df 100644 --- a/src/modules/startmanager/startmanager.cpp +++ b/src/modules/startmanager/startmanager.cpp @@ -12,6 +12,7 @@ #include "meminfo.h" #include "../../service/impl/application_manager.h" +#include #include #include @@ -37,12 +38,25 @@ StartManager::StartManager(QObject *parent) , m_autostartFiles(getAutostartList()) , m_isDBusCalled(false) { + waitForDeadChild(); loadSysMemLimitConfig(); getDesktopToAutostartMap(); listenAutostartFileEvents(); startAutostartProgram(); } +static void sig_child(int signo) +{ + int stat; + int pid; + while((pid = waitpid(-1, &stat, WNOHANG)) > 0); +} + +void StartManager::waitForDeadChild() +{ + signal(SIGCHLD, sig_child); +} + bool StartManager::addAutostart(const QString &desktop) { setIsDBusCalled(true); @@ -369,24 +383,26 @@ bool StartManager::doLaunchAppWithOptions(QString desktopFile, uint32_t timestam bool StartManager::launch(DesktopInfo *info, QString cmdLine, uint32_t timestamp, QStringList files) { - QProcess process; + QProcess process; // NOTE(black_desk): this QProcess not used to start, we + // have to manually fork and exec to set + // GIO_LAUNCHED_DESKTOP_FILE_PID. QStringList cmdPrefixesEnvs; - QStringList envs; + QProcessEnvironment envs = QProcessEnvironment::systemEnvironment(); QString appId(QString::fromStdString(info->getId())); bool useProxy = shouldUseProxy(appId); - for (QString var : QProcess::systemEnvironment()) { - if (useProxy && (var.startsWith("auto_proxy") - || var.startsWith("http_proxy") - || var.startsWith("https_proxy") - || var.startsWith("ftp_proxy") - || var.startsWith("all_proxy") - || var.startsWith("SOCKS_SERVER") - || var.startsWith("no_proxy"))) { - continue; - } - - envs << var; + if (useProxy) { + envs.remove("auto_proxy"); + envs.remove("AUTO_PROXY"); + envs.remove("http_proxy"); + envs.remove("HTTP_PROXY"); + envs.remove("https_proxy"); + envs.remove("HTTPS_PROXY"); + envs.remove("ftp_proxy"); + envs.remove("FTP_PROXY"); + envs.remove("SOCKS_SERVER"); + envs.remove("no_proxy"); + envs.remove("NO_PROXY"); } // FIXME: Don't using env to control the window scale factor, this function @@ -403,12 +419,10 @@ bool StartManager::launch(DesktopInfo *info, QString cmdLine, uint32_t timestamp double scale = ret.isValid() ? ret.value() : 1.0; scale = scale > 0 ? scale : 1; const QString scaleStr = QString::number(scale, 'f', -1); - envs << "DEEPIN_WINE_SCALE=" + scaleStr; + envs.insert("DEEPIN_WINE_SCALE", scaleStr); } } - envs << cmdPrefixesEnvs; - QStringList exeArgs; auto stdCmdLine = cmdLine.toStdString(); @@ -438,8 +452,8 @@ bool StartManager::launch(DesktopInfo *info, QString cmdLine, uint32_t timestamp QString exec = exeArgs[0]; exeArgs.removeAt(0); - qDebug() << "Launching app, desktop: " << QString::fromStdString(info->getFileName()) << " exec: " << exec - << " args: " << exeArgs << " useProxy:" << useProxy << "appid:" << appId << "envs:" << envs; + qDebug() << "Launching app, desktop:" << QString::fromStdString(info->getFileName()) << "exec:" << exec + << "args:" << exeArgs << "useProxy:" << useProxy << "appid:" << appId << "envs:" << envs.toStringList(); process.setProgram(exec); process.setArguments(exeArgs); @@ -447,17 +461,36 @@ bool StartManager::launch(DesktopInfo *info, QString cmdLine, uint32_t timestamp // NOTE(black_desk): This have to be done after load system environment. // Set same env twice in qt make the first one gone. - envs << QString("GIO_LAUNCHED_DESKTOP_FILE=") + - QString::fromStdString(info->getDesktopFile()->getFilePath()); + envs.insert("GIO_LAUNCHED_DESKTOP_FILE", QString::fromStdString(info->getDesktopFile()->getFilePath())); - process.setEnvironment(envs); - qint64 pid = 0; - if (process.startDetached(&pid)) { + qint64 pid = fork(); + if (pid == 0) { + envs.insert("GIO_LAUNCHED_DESKTOP_FILE_PID", QByteArray::number(getpid()).constData()); + auto argList = process.arguments(); + char const * args[argList.length() + 1]; + std::transform(argList.constBegin(), argList.constEnd(), args, [](const QString& str){ + auto byte = new QByteArray; + *byte = str.toUtf8(); + auto tmp_buf = byte->data(); + return tmp_buf; + }); + args[process.arguments().length()] = 0; + auto envStringList = envs.toStringList(); + char const * envs[envStringList.length() + 1]; + std::transform(envStringList.constBegin(), envStringList.constEnd(), envs, [](const QString& str){ + auto byte = new QByteArray; + *byte = str.toUtf8(); + auto tmp_buf = byte->data(); + return tmp_buf; + }); + envs[envStringList.length()] = 0; + execvpe(process.program().toLocal8Bit().constData(), (char**)args, (char**)envs); + exit(-1); + } else { if (useProxy) { qDebug() << "Launch the process[" << pid << "] by app proxy."; dbusHandler->addProxyProc(pid); } - return true; } return false; diff --git a/src/modules/startmanager/startmanager.h b/src/modules/startmanager/startmanager.h index e8b7abe..9770a5d 100644 --- a/src/modules/startmanager/startmanager.h +++ b/src/modules/startmanager/startmanager.h @@ -40,6 +40,7 @@ public Q_SLOTS: void onAutoStartupPathChange(const QString &dirPath); private: + void waitForDeadChild(); bool setAutostart(const QString &fileName, const bool value); bool doLaunchAppWithOptions(const QString &desktopFile); bool doLaunchAppWithOptions(QString desktopFile, uint32_t timestamp, QStringList files, QVariantMap options);