From 38cf02a51f2a17cabaf109ca38ebae63fb781f0c Mon Sep 17 00:00:00 2001 From: tanfeng Date: Wed, 25 May 2022 11:46:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20AM=20loader=E5=AE=9E=E7=8E=B0=E5=90=AF?= =?UTF-8?q?=E5=8A=A8freedesktop=E7=B1=BB=E5=9E=8B=E5=BA=94=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AM loader可以正常启动freedesktop类型应用了 Log: AM loader实现启动freedesktop类型应用 Task: https://pms.uniontech.com/task-view-108539.html Influence: AM loader Change-Id: If56835e638ca38ed53bcc7a0dddeca47e05cc8ba --- misc/systemd/CMakeLists.txt | 4 +- ...desktopspec.application.instance@.service} | 0 ...g.desktopspec.application.manager.service} | 4 +- src/loader/main.cpp | 136 ++++++++++++------ src/modules/methods/task.hpp | 38 +++-- src/service/impl/application_instance.cpp | 6 +- src/service/impl/application_manager.cpp | 8 +- src/service/main.cpp | 5 + 8 files changed, 138 insertions(+), 63 deletions(-) rename misc/systemd/{org.deskspec.application.instance@.service => org.desktopspec.application.instance@.service} (100%) rename misc/systemd/{org.deskspec.application.manager.service => org.desktopspec.application.manager.service} (51%) diff --git a/misc/systemd/CMakeLists.txt b/misc/systemd/CMakeLists.txt index 2edcb8e..a178d73 100644 --- a/misc/systemd/CMakeLists.txt +++ b/misc/systemd/CMakeLists.txt @@ -1,6 +1,6 @@ set(SYSTEMD_FILES - org.deskspec.application.instance@.service - org.deskspec.application.manager.service + org.desktopspec.application.instance@.service + org.desktopspec.application.manager.service ) install(FILES ${SYSTEMD_FILES} DESTINATION lib/systemd/user/) diff --git a/misc/systemd/org.deskspec.application.instance@.service b/misc/systemd/org.desktopspec.application.instance@.service similarity index 100% rename from misc/systemd/org.deskspec.application.instance@.service rename to misc/systemd/org.desktopspec.application.instance@.service diff --git a/misc/systemd/org.deskspec.application.manager.service b/misc/systemd/org.desktopspec.application.manager.service similarity index 51% rename from misc/systemd/org.deskspec.application.manager.service rename to misc/systemd/org.desktopspec.application.manager.service index 8b816ae..f7851d7 100644 --- a/misc/systemd/org.deskspec.application.manager.service +++ b/misc/systemd/org.desktopspec.application.manager.service @@ -3,6 +3,6 @@ Description=Deepin Application Manager service [Service] Type=DBus -BusName=org.deskspec.ApplicationManager -ExecStart=/usr/bin/deepin-application-service +BusName=org.desktopspec.ApplicationManager +ExecStart=/usr/bin/deepin-application-manager Slice=services.slice \ No newline at end of file diff --git a/src/loader/main.cpp b/src/loader/main.cpp index 2f6e82d..e4e56e3 100644 --- a/src/loader/main.cpp +++ b/src/loader/main.cpp @@ -18,6 +18,10 @@ #include #include +#include +#include +#include + #include "../modules/methods/basic.h" #include "../modules/methods/instance.hpp" #include "../modules/methods/quit.hpp" @@ -40,25 +44,16 @@ struct App { std::string id; }; -static App parseApp(const std::string& app) +static App parseApp(const QString& app) { - std::vector strings; - std::istringstream stream(app); - std::string s; - while (getline(stream, s, '/')) { - if (s.empty()) { - continue; - } - strings.push_back(s); - } - + QStringList values = app.split('/', QString::SkipEmptyParts); + qInfo() << "app:" << app << ", values size:" << values.size(); App result; - if (strings.size() == 3) { - result.prefix = strings[0]; - result.type = strings[1]; - result.id = strings[2]; + if (values.size() == 3) { + result.prefix = values.at(0).toStdString(); + result.type = values.at(1).toStdString(); + result.id = values.at(2).toStdString(); } - return result; } @@ -77,12 +72,51 @@ void sig_handler(int num) } } -int runLinglong(void* _arg) +// TODO: startManager合并流程? +int childFreedesktop(Methods::Task* task, std::string path) { - return 0; + prctl(PR_SET_PDEATHSIG, SIGKILL); + prctl(PR_SET_PDEATHSIG, SIGTERM); + prctl(PR_SET_PDEATHSIG, SIGHUP); + + DesktopDeconstruction dd(path); + dd.beginGroup("Desktop Entry"); + std::cout << dd.value("Exec") << std::endl; + + QStringList envs; + for (auto it = task->environments.begin(); it != task->environments.end(); ++it) { + envs.append(it.key() + "=" + it.value()); + } + + QStringList exeArgs; + exeArgs << QString::fromStdString(dd.value("Exec")).split(" "); + + QString exec = exeArgs[0]; + exeArgs.removeAt(0); + + pid_t pid = fork(); + if (pid == -1) { + perror("fork()"); + return -1; + } + + if (pid == 0) { + // 子进程 + QProcess process; + qInfo() << "exec:" << exec; + qInfo() << "exeArgs:" << exeArgs; + process.setWorkingDirectory(QDir::homePath()); + process.setEnvironment(envs); + process.start(exec, exeArgs); + process.waitForFinished(-1); + process.close(); + qInfo() << "process finish"; + exit(0); + } + return pid; } -int child(Methods::Task* task, std::string path) +int childLinglong(Methods::Task* task, std::string path) { prctl(PR_SET_PDEATHSIG, SIGKILL); prctl(PR_SET_PDEATHSIG, SIGTERM); @@ -179,6 +213,12 @@ int child(Methods::Task* task, std::string path) return pid; } +int childAndroid(Methods::Task* task, std::string path) +{ + // TODO + return 0; +} + #define DAM_TASK_HASH "DAM_TASK_HASH" #define DAM_TASK_TYPE "DAM_TASK_TYPE" @@ -203,14 +243,14 @@ int main(int argc, char* argv[]) // 初始化应用注册信息 QByteArray registerArray; Methods::Registe registe; - registe.id = dam_task_type; + registe.id = dam_task_type; registe.hash = dam_task_hash; Methods::toJson(registerArray, registe); // 向AM注册应用信息进行校验 Methods::Registe registe_result; registe_result.state = false; - QByteArray result = client.get(registerArray); + QByteArray result = client.get(registerArray); if (!result.isEmpty()) { Methods::fromJson(result, registe_result); } @@ -228,50 +268,66 @@ int main(int argc, char* argv[]) result = client.get(instanceArray); Methods::Task task; Methods::fromJson(result, task); // fromJson TODO 数据解析异常 - qWarning() << "[result] " << result; + qInfo() << "[Task] " << result; // 校验task内容 - App app = parseApp(task.runId.toStdString()); + App app = parseApp(task.runId); + qInfo() << "[App] " + << "prefix:" << QString::fromStdString(app.prefix) + << "type:" << QString::fromStdString(app.type) + << "id:" << QString::fromStdString(app.id); if (task.id.isEmpty() || app.id.empty() || app.type.empty() || app.prefix.empty()) { std::cout << "get task error" << std::endl; return -4; } - - std::string path{ "/usr/share/applications/" + app.id + ".desktop" }; - if (app.type == "user") { - struct passwd* user = getpwuid(getuid()); - path = std::string(user->pw_dir) + "/.local/share/applications/" + app.id + ".desktop"; + if (app.prefix != "freedesktop" + && app.prefix != "linglong" + && app.prefix != "android") { + qWarning() << "error app prefix :" << QString::fromStdString(app.type); + return -1; } pthread_attr_t attr; - size_t stack_size; + size_t stack_size; pthread_attr_init(&attr); pthread_attr_getstacksize(&attr, &stack_size); pthread_attr_destroy(&attr); /* 先将SIGCHLD信号阻塞 保证在子进程结束前设置父进程的捕捉函数 */ sigset_t nmask, omask; - sigemptyset(&nmask); - sigaddset(&nmask, SIGCHLD); - sigprocmask(SIG_BLOCK, &nmask, &omask); + // sigemptyset(&nmask); + // sigaddset(&nmask, SIGCHLD); + // sigprocmask(SIG_BLOCK, &nmask, &omask); //char* stack = (char*) malloc(stack_size); //pid_t pid = clone(child, stack + stack_size, CLONE_NEWPID | SIGCHLD, static_cast(&task)); - pid_t pid = child(&task, path); + pid_t pid = -1; + if (app.prefix == "freedesktop") { + pid = childFreedesktop(&task, task.filePath.toStdString()); + } else if (app.prefix == "linglong") { + pid = childLinglong(&task, task.filePath.toStdString()); + } else if (app.prefix == "android") { + pid = childAndroid(&task, task.filePath.toStdString()); + } else { + qWarning() << "error app prefix:" << QString::fromStdString(app.prefix); + } + // TODO: 启动线程,创建新的连接去接受服务器的消息 + // TODO:信号处理有问题 /* 设置捕捉函数 */ - struct sigaction sig; - sig.sa_handler = sig_handler; - sigemptyset(&sig.sa_mask); - sig.sa_flags = 0; - sigaction(SIGCHLD, &sig, NULL); + // struct sigaction sig; + // sig.sa_handler = sig_handler; + // sigemptyset(&sig.sa_mask); + // sig.sa_flags = 0; + // sigaction(SIGCHLD, &sig, NULL); /* 然后再unblock */ - sigdelset(&omask, SIGCHLD); - sigprocmask(SIG_SETMASK, &omask, NULL); + // sigdelset(&omask, SIGCHLD); + // sigprocmask(SIG_SETMASK, &omask, NULL); int exitCode; waitpid(pid, &exitCode, 0); + qInfo() << "app exitCode:" << exitCode; Methods::Quit quit; quit.code = exitCode; diff --git a/src/modules/methods/task.hpp b/src/modules/methods/task.hpp index 8ea08b6..3ddf07d 100644 --- a/src/modules/methods/task.hpp +++ b/src/modules/methods/task.hpp @@ -18,6 +18,7 @@ namespace Methods QString runId; QString type{"task"}; QString date; + QString filePath; QList arguments; QMap environments; }; @@ -36,7 +37,8 @@ namespace Methods QJsonObject obj = { {"type", task.type}, {"id", task.id}, - {"run_id", task.runId}, + {"runId", task.runId}, + {"filePath", task.filePath}, {"date", task.date}, {"arguments", argArray}, {"environments", QJsonObject::fromVariantMap(envsMap)} @@ -51,24 +53,30 @@ namespace Methods qWarning() << "fromJson task failed"; return; } - QJsonObject obj = doc.object(); - if (!obj.contains("id") || !obj.contains("runId") || !obj.contains("date") \ - || !obj.contains("arguments") || !obj.contains("environments")) { - qWarning() << "id runId date arguments environments not exist in task array"; - return; + if (obj.contains("id")) { + task.id = obj.value("id").toString(); + } + if (obj.contains("runId")) { + task.runId = obj.value("runId").toString(); + } + if (obj.contains("filePath")) { + task.filePath = obj.value("filePath").toString(); + } + if (obj.contains("date")) { + task.date = obj.value("date").toString(); } - task.id = obj.value("id").toString(); - task.runId = obj.value("runId").toString(); - task.date = obj.value("date").toString(); - for (auto arg : obj.value("arguments").toArray()) { - task.arguments.append(arg.toString()); + if (obj.contains("arguments")) { + for (auto arg : obj.value("arguments").toArray()) { + task.arguments.append(arg.toString()); + } } - - QVariantMap envsMap = obj.value("environments").toObject().toVariantMap(); - for (auto it = envsMap.constBegin(); it != envsMap.constEnd(); ++it) { - task.environments.insert(it.key(), it.value().toString()); + if (obj.contains("environments")) { + QVariantMap envsMap = obj.value("environments").toObject().toVariantMap(); + for (auto it = envsMap.constBegin(); it != envsMap.constEnd(); ++it) { + task.environments.insert(it.key(), it.value().toString()); + } } } } // namespace Methods diff --git a/src/service/impl/application_instance.cpp b/src/service/impl/application_instance.cpp index aa91243..356e439 100644 --- a/src/service/impl/application_instance.cpp +++ b/src/service/impl/application_instance.cpp @@ -68,8 +68,9 @@ public: emit q_ptr->taskFinished(p->exitCode()); } #else + qInfo() << "app manager load service:" << QString("org.desktopspec.application.instance@%1.service").arg(m_id); QDBusInterface systemd("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager"); - QDBusReply reply = systemd.call("StartUnit", QString("org.deskspec.application.instance@%1.service").arg(m_id), "replace-irreversibly"); + QDBusReply reply = systemd.call("StartUnit", QString("org.desktopspec.application.instance@%1.service").arg(m_id), "replace-irreversibly"); if (!reply.isValid()) { qInfo() << reply.error(); q_ptr->deleteLater(); @@ -82,7 +83,7 @@ public: #ifdef LOADER_PATH #else QDBusInterface systemd("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager"); - qInfo() << systemd.call("StopUnit", QString("org.deskspec.application.instance@%1.service").arg(m_id), "replace-irreversibly"); + qInfo() << systemd.call("StopUnit", QString("org.desktopspec.application.instance@%1.service").arg(m_id), "replace-irreversibly"); #endif } @@ -146,6 +147,7 @@ Methods::Task ApplicationInstance::taskInfo() const Methods::Task task; task.id = d->m_id; task.runId = d->application->id(); + task.filePath = d->application->filePath(); task.date = QString::number(startuptime()); task.arguments = m_files; diff --git a/src/service/impl/application_manager.cpp b/src/service/impl/application_manager.cpp index ea70035..22751b7 100644 --- a/src/service/impl/application_manager.cpp +++ b/src/service/impl/application_manager.cpp @@ -90,8 +90,11 @@ void ApplicationManagerPrivate::recvClientData(int socket, const std::vector lock(task_mutex); for (auto it = tasks.begin(); it != tasks.end(); ++it) { - result.state = true; - result.hash = QString::fromStdString(it->first); + if (registe.hash == QString::fromStdString(it->first)) { + result.state = true; + result.hash = registe.hash; + break; + } } Methods::toJson(tmpArray, result); write(socket, tmpArray.toStdString()); @@ -199,6 +202,7 @@ QList ApplicationManager::GetInstances(const QString &id) */ QDBusObjectPath ApplicationManager::Launch(const QString &id, QStringList files) { + qInfo() << "Launch " << id; Q_D(ApplicationManager); if (!d->checkDMsgUid()) return {}; diff --git a/src/service/main.cpp b/src/service/main.cpp index d1791f2..a82dea7 100644 --- a/src/service/main.cpp +++ b/src/service/main.cpp @@ -90,6 +90,11 @@ int main(int argc, char *argv[]) QDBusConnection::sessionBus().registerObject(app->path().path(), "org.desktopspec.Application", app.get()); } + for (const QSharedPointer &app : apps) { + qInfo() << "appId - " << app->id(); + qInfo() << "appFilePath - " << app->filePath(); + } + ApplicationManager::instance()->addApplication(apps); ApplicationManager::instance()->launchAutostartApps();