Skip to content

fix(cli): wait out slow PackageManager1 activation (closes #1338)#1743

Open
123123213weqw wants to merge 1 commit into
OpenAtom-Linyaps:masterfrom
123123213weqw:wangyue/issue-1338
Open

fix(cli): wait out slow PackageManager1 activation (closes #1338)#1743
123123213weqw wants to merge 1 commit into
OpenAtom-Linyaps:masterfrom
123123213weqw:wangyue/issue-1338

Conversation

@123123213weqw

Copy link
Copy Markdown
Contributor

Summary

ll-cli failed with Failed to activate org.deepin.linglong.PackageManager1 QDBusError("org.freedesktop.DBus.Error.NoReply", ...) on systems such as Ubuntu Kylin 25.04 and Arch Linux (#1338), preventing installs from working even though the package itself was installed.

Root cause

Cli::initializeDBusPackageManager() waits for the package manager daemon to be reachable by issuing a single org.freedesktop.DBus.Peer.Ping() (libs/linglong/src/linglong/cli/cli.cpp, waitForDBusPeerReady) using the default D-Bus call timeout of 25s.

The daemon (org.deepin.linglong.PackageManager1) is D-Bus activated: the first Ping() asks systemd to start org.deepin.linglong.PackageManager.service (Type=dbus), and the daemon only acquires its well-known bus name after starting up and initializing the local ostree repository. On a cold start (and on slower systems/distros), this whole sequence can take longer than the single 25s window, so the one-shot Ping() times out and ll-cli reports a hard, cryptic NoReply failure and aborts.

Fix

waitForDBusPeerReady now polls instead of giving up on the first timeout:

  • retry Ping() with a short per-call timeout (5s) up to an overall deadline of 90s, which matches systemd's default Type=dbus unit timeout — so a slow but successful activation is waited out rather than treated as a failure;
  • on success it returns immediately; on terminal failure after the deadline it surfaces the underlying error.

The initializeDBusPackageManager() error message now also points the user at the daemon service status and journal, so a genuinely broken daemon can be diagnosed:

Failed to activate org.deepin.linglong.PackageManager1; check the daemon with
'systemctl status org.deepin.linglong.PackageManager' and
'journalctl -u org.deepin.linglong.PackageManager -e'

The change applies to both activation paths (system bus and --no-dbus peer mode) since both go through waitForDBusPeerReady.

Files changed

  • libs/linglong/src/linglong/cli/cli.cpp
    • waitForDBusPeerReady: bounded retry loop with a per-call timeout and a 90s total deadline.
    • Cli::initializeDBusPackageManager: clearer, actionable activation error message.

Verification

Built from source on Debian/trixie with the project's debug CMake preset (Qt5, ostree, systemd, etc.):

  • cmake --preset debug -G Ninja configured cleanly.
  • Built linglong lib, ll-cli, ll-package-manager, and ll-tests — all link successfully; no new warnings in the edited regions (remaining -Wmissing-field-initializers warnings are pre-existing in unrelated functions).
  • clang-format (repo .clang-format) produces zero changes on the edited file.
  • Targeted tests pass: ll-tests --gtest_filter='Cli*:*RepoAndPackageManager*'20/20 PASSED.
  • The 1 failing test (Error.WarpStdErrorCode) and the LayerPackagerTest/UabFileTest suite-setup failures are pre-existing and environmental: they reproduce identically on the unmodified tree (verified via git stash/rebuild) and are caused by running as root and missing FUSE tooling in this container, not by this change.

Notes / assumptions

  • The 90s overall deadline intentionally matches systemd's default Type=dbus TimeoutSec so the client waits at least as long as the daemon's supervisor does.
  • waitForDBusPeerReady is a file-local helper, so the retry logic is covered indirectly by the existing CliRepoAndPackageManager* tests (which exercise the surrounding getPkgMan/getRepo flow). A direct unit test would require mocking a QDBusConnection, which is out of scope for this minimal fix.

Closes #1338.

ll-cli probed org.deepin.linglong.PackageManager1 with a single Ping()
that used the default 25s D-Bus timeout. The package manager daemon is
D-Bus activated: before it can acquire its well-known bus name it has to
be started by systemd and initialize the local ostree repository. On a
cold start (and on slower systems/distros such as Ubuntu Kylin and Arch)
this can exceed the single 25s window, so ll-cli surfaced a cryptic
"org.freedesktop.DBus.Error.NoReply" and gave up immediately, which is
what issue OpenAtom-Linyaps#1338 reports.
Poll the peer instead: retry Ping() with a short per-call timeout up to
a 90s overall deadline (matching systemd's default Type=dbus unit
timeout), so a slow but successful activation is waited out rather than
reported as a hard failure. When activation ultimately fails, point the
user at the daemon service status and journal for actionable diagnostics.
Closes OpenAtom-Linyaps#1338.
Log: ll-cli now retries the PackageManager1 readiness check instead of
failing on the first D-Bus timeout.
Influence: only affects ll-cli's PackageManager1 activation path
(waitForDBusPeerReady and the activation error message); no public API
or behavior change for an already-running daemon.

Signed-off-by: 王越 <1939455790@qq.com>
@deepin-ci-robot

Copy link
Copy Markdown
Collaborator

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: 123123213weqw

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

@deepin-ci-robot

Copy link
Copy Markdown
Collaborator

Hi @123123213weqw. Thanks for your PR.

I'm waiting for a OpenAtom-Linyaps member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@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 implements a retry loop in waitForDBusPeerReady to wait for a DBus peer to become ready, using a 90-second total deadline, a 5-second timeout per call, and a 1-second retry interval. It also improves the error message when failing to activate the DBus package manager by providing systemd troubleshooting commands. The review feedback suggests optimizing the retry loop by instantiating the DBusPeer object and setting its timeout once outside the loop instead of recreating it on every iteration.

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 on lines +130 to +141
using namespace std::chrono_literals;

return LINGLONG_OK;
constexpr auto perCallTimeout = 5s;
constexpr auto retryInterval = 1s;
constexpr auto totalDeadline = 90s;

const auto startedAt = std::chrono::steady_clock::now();
while (true) {
auto peer = linglong::api::dbus::v1::DBusPeer(service, path, connection);
peer.setTimeout(static_cast<int>(std::chrono::milliseconds(perCallTimeout).count()));

auto reply = peer.Ping();

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.

medium

Recreating the DBusPeer object and setting its timeout on every single iteration of the loop is inefficient and unnecessary. We can instantiate peer and set its timeout once outside the loop. Additionally, defining perCallTimeout directly in milliseconds (5000ms) simplifies the setTimeout call by avoiding the need for explicit duration conversion.

    using namespace std::chrono_literals;

    constexpr auto perCallTimeout = 5000ms;
    constexpr auto retryInterval = 1s;
    constexpr auto totalDeadline = 90s;

    auto peer = linglong::api::dbus::v1::DBusPeer(service, path, connection);
    peer.setTimeout(static_cast<int>(perCallTimeout.count()));

    const auto startedAt = std::chrono::steady_clock::now();
    while (true) {
        auto reply = peer.Ping();

@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

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

Files with missing lines Patch % Lines
libs/linglong/src/linglong/cli/cli.cpp 0.00% 14 Missing ⚠️
Files with missing lines Coverage Δ
libs/linglong/src/linglong/cli/cli.cpp 2.63% <0.00%> (-0.02%) ⬇️

... and 1 file with indirect coverage changes

🚀 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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error on Ubuntu Kylin 25.04/Ubuntu Kylin 25.04 中的错误

2 participants