Skip to content

feat: avoid duplicate ll-package-manager startup by checking existing#1710

Merged
dengbo11 merged 2 commits into
OpenAtom-Linyaps:release/1.13from
dengbo11:release-1.13
Jun 30, 2026
Merged

feat: avoid duplicate ll-package-manager startup by checking existing#1710
dengbo11 merged 2 commits into
OpenAtom-Linyaps:release/1.13from
dengbo11:release-1.13

Conversation

@dengbo11

Copy link
Copy Markdown
Collaborator

connection

  1. Add startProcess helper to launch detached processes with proper environment and cleanup on exit.
  2. Replace unconditional startDetached and sleep with a D-Bus peer connection check to see if ll-package-manager is already running.
  3. Only start a new process when no existing daemon is detected; otherwise log reuse of existing instance.
  4. Include signal handling to terminate spawned processes when the application quits.

Log: Improved process management for ll-package-manager to prevent duplicate instances.

Influence:

  1. Verify that ll-package-manager starts correctly when not already running.
  2. Test that when ll-package-manager is already running, a new process is not spawned.
  3. Confirm that spawned processes are terminated when the main application exits.
  4. Check logging output for "reuse existing process" or "start" messages.
  5. Verify D-Bus connection to the peer socket works as expected.
  6. Test in scenarios where the socket file might be stale or missing.

dengbo11 added 2 commits June 30, 2026 09:47
connection

1. Add `startProcess` helper to launch detached processes with proper
environment and cleanup on exit.
2. Replace unconditional `startDetached` and sleep with a D-Bus peer
connection check to see if `ll-package-manager` is already running.
3. Only start a new process when no existing daemon is detected;
otherwise log reuse of existing instance.
4. Include signal handling to terminate spawned processes when the
application quits.

Log: Improved process management for ll-package-manager to prevent
duplicate instances.

Influence:
1. Verify that ll-package-manager starts correctly when not already
running.
2. Test that when ll-package-manager is already running, a new process
is not spawned.
3. Confirm that spawned processes are terminated when the main
application exits.
4. Check logging output for "reuse existing process" or "start"
messages.
5. Verify D-Bus connection to the peer socket works as expected.
6. Test in scenarios where the socket file might be stale or missing.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a check to see if ll-package-manager is already running via a peer DBus connection before attempting to start a new instance. If it is not running, a new helper function startProcess is used to start it detached and register a cleanup callback to terminate the process when the application quits. The review feedback highlights critical issues in startProcess: first, calling process.environment() on a new QProcess returns an empty list, which wipes out the system environment; second, if startDetached fails, the PID remains 0, leading to a dangerous kill(0, SIGTERM) call that terminates the entire process group. Additionally, the reviewer notes that using the connection name "ll-package-manager" for the temporary check can conflict with subsequent connections, and suggests using a distinct name and explicitly disconnecting.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread apps/ll-cli/src/main.cpp
Comment on lines +52 to +70
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);
});
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

There are two critical issues in the startProcess helper function:

  1. Environment Wiping: Calling process.environment() on a newly constructed QProcess returns an empty list. Appending "QT_FORCE_STDERR_LOGGING=1" and calling process.setEnvironment(envs) replaces the entire environment of the child process with just this single variable. This discards all system environment variables (such as PATH, LD_LIBRARY_PATH, USER, etc.), which will cause sudo or ll-package-manager to fail to start or run incorrectly. Use QProcess::systemEnvironment() to preserve the parent process's environment.

  2. Dangerous Signal Handling: If process.startDetached(&pid) fails, pid remains 0. Calling kill(0, SIGTERM) inside the aboutToQuit lambda will send SIGTERM to the entire process group of ll-cli, abruptly terminating the CLI itself and potentially other sibling/parent processes. You must check that startDetached succeeded and that pid > 0 before registering the cleanup connection.

void startProcess(const QString &program, const QStringList &args = {})
{
    QProcess process;
    auto envs = QProcess::systemEnvironment();
    envs.push_back("QT_FORCE_STDERR_LOGGING=1");
    process.setEnvironment(envs);
    process.setProgram(program);
    process.setArguments(args);

    qint64 pid = 0;
    if (process.startDetached(&pid) && pid > 0) {
        LogD("start {} {} as {}", program.toStdString(), args.join(" ").toStdString(), pid);

        QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, [pid]() {
            LogD("kill {}", pid);
            kill(pid, SIGTERM);
        });
    } else {
        LogE("failed to start process: {}", program.toStdString());
    }
}

Comment thread apps/ll-cli/src/main.cpp
Comment on lines +717 to +734
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");
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using the connection name "ll-package-manager" for the temporary startup check can conflict with the actual connection established later in cli.cpp (line 471).

If the connection is not fully unregistered or closed immediately upon the destruction of pkgManConn (due to Qt's internal DBus thread handling or event loop delays), the subsequent connectToPeer call in cli.cpp will fail with a "connection already exists" error, preventing ll-cli from working in --no-dbus mode.

To prevent this, use a distinct connection name (e.g., "ll-package-manager-check") and explicitly disconnect from it once the check is complete.

        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");
        }

@deepin-ci-robot

Copy link
Copy Markdown
Collaborator

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: dengbo11

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

1 similar comment
@deepin-ci-robot

Copy link
Copy Markdown
Collaborator

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: dengbo11

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@dengbo11 dengbo11 merged commit f00a954 into OpenAtom-Linyaps:release/1.13 Jun 30, 2026
12 of 14 checks passed
@codecov

codecov Bot commented Jun 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 20 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
apps/ll-cli/src/main.cpp 0.00% 20 Missing ⚠️
Files with missing lines Coverage Δ
apps/ll-cli/src/main.cpp 0.00% <0.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants