-
Notifications
You must be signed in to change notification settings - Fork 65
feat: avoid duplicate ll-package-manager startup by checking existing #1710
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,12 +20,13 @@ | |
| #include "linglong/utils/log/log.h" | ||
| #include "ocppi/cli/crun/Crun.hpp" | ||
|
|
||
| #include <CLI/CLI.hpp> | ||
| #include <sys/file.h> | ||
|
|
||
| #include <QDBusConnection> | ||
| #include <QDBusMetaType> | ||
| #include <QDBusObjectPath> | ||
| #include <QJsonDocument> | ||
| #include <QJsonObject> | ||
| #include <QProcess> | ||
| #include <QtGlobal> | ||
|
|
@@ -35,10 +36,11 @@ | |
| #include <map> | ||
| #include <memory> | ||
| #include <string_view> | ||
| #include <thread> | ||
|
|
||
| #include <fcntl.h> | ||
| #include <signal.h> | ||
| #include <unistd.h> | ||
| #include <wordexp.h> | ||
|
|
||
| using namespace linglong::utils::error; | ||
|
|
@@ -47,6 +49,26 @@ | |
|
|
||
| namespace { | ||
|
|
||
| void startProcess(const QString &program, const QStringList &args = {}) | ||
| { | ||
| QProcess process; | ||
| auto envs = process.environment(); | ||
| envs.push_back("QT_FORCE_STDERR_LOGGING=1"); | ||
| process.setEnvironment(envs); | ||
| process.setProgram(program); | ||
| process.setArguments(args); | ||
|
|
||
| qint64 pid = 0; | ||
| process.startDetached(&pid); | ||
|
|
||
| LogD("start {} {} as {}", program.toStdString(), args.join(" ").toStdString(), pid); | ||
|
|
||
| QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, [pid]() { | ||
| LogD("kill {}", pid); | ||
| kill(pid, SIGTERM); | ||
| }); | ||
| } | ||
|
|
||
| std::vector<std::string> transformOldExec(int argc, char **argv) noexcept | ||
| { | ||
| std::vector<std::string> res; | ||
|
|
@@ -692,16 +714,24 @@ | |
| return -1; | ||
| } | ||
|
|
||
| // Start ll-package-manager --no-dbus first to initialize the repository | ||
| QProcess::startDetached("sudo", | ||
| { "--user", | ||
| LINGLONG_USERNAME, | ||
| "--preserve-env=QT_FORCE_STDERR_LOGGING", | ||
| "--preserve-env=QDBUS_DEBUG", | ||
| LINGLONG_LIBEXEC_DIR "/ll-package-manager", | ||
| "--no-dbus" }); | ||
| using namespace std::chrono_literals; | ||
| std::this_thread::sleep_for(1s); | ||
| const auto pkgManAddress = QString("unix:path=/tmp/linglong-package-manager.socket"); | ||
|
|
||
| // Check if ll-package-manager is already running | ||
| auto pkgManConn = QDBusConnection::connectToPeer(pkgManAddress, "ll-package-manager"); | ||
| if (!pkgManConn.isConnected()) { | ||
| // Only start a new process if no existing one is listening | ||
| startProcess("sudo", | ||
| { "--user", | ||
| LINGLONG_USERNAME, | ||
| "--preserve-env=QT_FORCE_STDERR_LOGGING", | ||
| "--preserve-env=QDBUS_DEBUG", | ||
| LINGLONG_LIBEXEC_DIR "/ll-package-manager", | ||
| "--no-dbus" }); | ||
| using namespace std::chrono_literals; | ||
| std::this_thread::sleep_for(1s); | ||
| } else { | ||
| LogD("ll-package-manager is already running, reuse existing process"); | ||
| } | ||
|
Comment on lines
+717
to
+734
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using the connection name If the connection is not fully unregistered or closed immediately upon the destruction of To prevent this, use a distinct connection name (e.g., const auto pkgManAddress = QString("unix:path=/tmp/linglong-package-manager.socket");
// Check if ll-package-manager is already running
bool alreadyRunning = false;
{
auto checkConn = QDBusConnection::connectToPeer(pkgManAddress, "ll-package-manager-check");
if (checkConn.isConnected()) {
alreadyRunning = true;
QDBusConnection::disconnectFromPeer("ll-package-manager-check");
}
}
if (!alreadyRunning) {
// Only start a new process if no existing one is listening
startProcess("sudo",
{ "--user",
LINGLONG_USERNAME,
"--preserve-env=QT_FORCE_STDERR_LOGGING",
"--preserve-env=QDBUS_DEBUG",
LINGLONG_LIBEXEC_DIR "/ll-package-manager",
"--no-dbus" });
using namespace std::chrono_literals;
std::this_thread::sleep_for(1s);
} else {
LogD("ll-package-manager is already running, reuse existing process");
} |
||
| } | ||
| auto repo = linglong::repo::OSTreeRepo::loadFromPath(LINGLONG_ROOT); | ||
| if (!repo.has_value()) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two critical issues in the
startProcesshelper function:Environment Wiping: Calling
process.environment()on a newly constructedQProcessreturns an empty list. Appending"QT_FORCE_STDERR_LOGGING=1"and callingprocess.setEnvironment(envs)replaces the entire environment of the child process with just this single variable. This discards all system environment variables (such asPATH,LD_LIBRARY_PATH,USER, etc.), which will causesudoorll-package-managerto fail to start or run incorrectly. UseQProcess::systemEnvironment()to preserve the parent process's environment.Dangerous Signal Handling: If
process.startDetached(&pid)fails,pidremains0. Callingkill(0, SIGTERM)inside theaboutToQuitlambda will sendSIGTERMto the entire process group ofll-cli, abruptly terminating the CLI itself and potentially other sibling/parent processes. You must check thatstartDetachedsucceeded and thatpid > 0before registering the cleanup connection.