Skip to content

test: run the screensaver bus test without dbus-run-session - #196

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
fly602:fix/power-screensaver-test-bus
Oct 15, 2026
Merged

deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
fly602:fix/power-screensaver-test-bus

Conversation

@fly602

@fly602 fly602 commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

The power screensaver D-Bus test is driven through dbus-run-session, which
shuts its private bus down by signalling dbus-daemon. On UOS kernels the
usec LSM labels that binary deepin_unkillable_t and denies the signal:

uavc: denied { signal } for comm="dbus-run-sessio"
  scontext=system_u:object_r:deepin_usec_t:s0
  tcontext=system_u:object_r:deepin_unkillable_t:s0 tclass=process

So dbus-run-session waits forever for its daemon, and because that daemon
inherited the test runner's stdout pipe, ctest never sees EOF and reports a
timeout even though the test itself finished and passed in 364 ms.

A second failure appears in the packaging path: dpkg-buildpackage runs under
fakeroot, whose libfakeroot-sysv.so is injected via LD_PRELOAD and fakes
getuid() as 0. The client then authenticates with AUTH EXTERNAL 30 while
the daemon checks the real uid through SO_PEERCRED and refuses the
connection, so every registerObject/registerService call fails.

This change runs the test through a small wrapper instead:

  • a dbus-daemon --fork private bus whose stdio goes to /dev/null, so a
    daemon that survives cleanup can never hold a pipe of the test runner open;
  • best-effort cleanup that does not turn "cannot signal the daemon" into a
    test failure;
  • LD_PRELOAD cleared before the bus starts, restoring the real uid.

debian/changelog is intentionally not touched; the version bump is generated
by the update-changelog workflow.

Verification

Scenario Before After
ctest (whole suite) 14/15, power-screensaver-proxy timed out at 20 s 15/15 in ~2.7 s
ctest -R power-screensaver-proxy 20.02 s timeout 0.38 s pass
fakeroot -- dh_auto_test (packaging) registerObject failed 15/15 pass
ctest | cat, make test hang <3 s
clean configure + build — 0.38 s pass

Residual cost: on kernels where the LSM denies the signal, one idle
dbus-daemon is left behind (a few MB); it no longer affects the test result.

Summary by Sourcery

Run the power screensaver D-Bus test through a resilient private-bus wrapper instead of dbus-run-session.

Bug Fixes:

  • Prevent the power screensaver D-Bus test from hanging or timing out on systems where LSM restrictions interfere with dbus-run-session cleanup.
  • Fix packaging-test failures under fakeroot by ensuring the private bus authenticates clients using their real user identity.

Enhancements:

  • Run the screensaver test against an independently started private D-Bus daemon with isolated standard streams and best-effort cleanup.

Tests:

  • Ensure the screensaver D-Bus test uses the new private-bus wrapper across CTest and packaging test runs.

@sourcery-ai

sourcery-ai Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

The PR replaces dbus-run-session with a shell wrapper that launches an isolated, detached dbus-daemon, avoids inherited test-runner pipes and fakeroot UID spoofing, and treats daemon cleanup as best effort so the screensaver D-Bus test completes reliably on restricted kernels and in packaging builds.

File-Level Changes

Change Details Files
Replace dbus-run-session with a dedicated private-bus launcher for the screensaver test.
  • Locate dbus-daemon during configuration and pass its path to the test.
  • Start a forked private daemon with all standard streams detached and capture its address and PID.
  • Export the private bus address before executing the test, then perform non-fatal daemon cleanup while preserving the test exit status.
src/plugin-qt/power/session/tests/CMakeLists.txt
src/plugin-qt/power/session/tests/run-with-private-bus.sh
Make the test work when invoked through fakeroot.
  • Clear LD_PRELOAD before starting the bus and running the test so fakeroot's UID interception cannot break EXTERNAL authentication.
src/plugin-qt/power/session/tests/run-with-private-bus.sh

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 2 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/plugin-qt/power/session/tests/run-with-private-bus.sh" line_range="61-63" />
<code_context>
+bus_address=$(cat "$address_file")
+daemon_pid=$(cat "$pid_file")
+if [ -z "$bus_address" ]; then
+    echo "$0: dbus-daemon did not print a bus address" >&2
+    exit 1
+fi
+
+DBUS_SESSION_BUS_ADDRESS=$bus_address
</code_context>
<issue_to_address>
**Private bus survives failed startup**

When `dbus-daemon` forks but writes no address, the `bus_address` check exits before the normal `kill` block, and the `EXIT` trap only removes temporary files; the private bus remains running after startup fails.

Route this exit through daemon cleanup before returning.

Also at `src/plugin-qt/power/session/tests/run-with-private-bus.sh:47`.
</issue_to_address>

### Comment 2
<location path="src/plugin-qt/power/session/tests/run-with-private-bus.sh" line_range="47" />
<code_context>
+
+address_file=$(mktemp) || exit 1
+pid_file=$(mktemp) || exit 1
+trap 'rm -f "$address_file" "$pid_file"' EXIT HUP INT TERM
+
+# stdin and both output streams to /dev/null: a daemon that survives cleanup
</code_context>
<issue_to_address>
**Signals leave tests running**

When the wrapper receives `HUP`, `INT`, or `TERM` while its command remains alive and does not receive the signal, the signal trap only removes temporary files, so the wrapper remains blocked waiting for the command and never reaches normal daemon cleanup; the command and private bus keep running until it returns.

Make the signal trap terminate the command and run daemon cleanup.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment on lines +61 to +63
echo "$0: dbus-daemon did not print a bus address" >&2
exit 1
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Medium · Private bus survives failed startup

When dbus-daemon forks but writes no address, the bus_address check exits before the normal kill block, and the EXIT trap only removes temporary files; the private bus remains running after startup fails.

Route this exit through daemon cleanup before returning.

Also at src/plugin-qt/power/session/tests/run-with-private-bus.sh:47.

Prompt for AI agents
In `src/plugin-qt/power/session/tests/run-with-private-bus.sh` at lines 61-63:

**Private bus survives failed startup**

When `dbus-daemon` forks but writes no address, the `bus_address` check exits before the normal `kill` block, and the `EXIT` trap only removes temporary files; the private bus remains running after startup fails.

Route this exit through daemon cleanup before returning.

Also at `src/plugin-qt/power/session/tests/run-with-private-bus.sh:47`.


address_file=$(mktemp) || exit 1
pid_file=$(mktemp) || exit 1
trap 'rm -f "$address_file" "$pid_file"' EXIT HUP INT TERM

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Medium · Signals leave tests running

When the wrapper receives HUP, INT, or TERM while its command remains alive and does not receive the signal, the signal trap only removes temporary files, so the wrapper remains blocked waiting for the command and never reaches normal daemon cleanup; the command and private bus keep running until it returns.

Make the signal trap terminate the command and run daemon cleanup.

Prompt for AI agents
In `src/plugin-qt/power/session/tests/run-with-private-bus.sh` at line 47:

**Signals leave tests running**

When the wrapper receives `HUP`, `INT`, or `TERM` while its command remains alive and does not receive the signal, the signal trap only removes temporary files, so the wrapper remains blocked waiting for the command and never reaches normal daemon cleanup; the command and private bus keep running until it returns.

Make the signal trap terminate the command and run daemon cleanup.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/plugin-qt/power/session/tests/run-with-private-bus.sh" line_range="47" />
<code_context>
+
+address_file=$(mktemp) || exit 1
+pid_file=$(mktemp) || exit 1
+trap 'rm -f "$address_file" "$pid_file"' EXIT HUP INT TERM
+
+# stdin and both output streams to /dev/null: a daemon that survives cleanup
</code_context>
<issue_to_address>
**Early exits leave bus daemons**

When the command is interrupted or times out, or `dbus-daemon` starts without printing a bus address, the trap removes the PID file without signaling the daemon; interruption skips the end-of-script `kill`, and the missing-address path exits immediately, leaving the private bus running.

Make exit and signal cleanup read the PID and signal the daemon before removing the temporary files.

Also at `src/plugin-qt/power/session/tests/run-with-private-bus.sh:63`.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨


address_file=$(mktemp) || exit 1
pid_file=$(mktemp) || exit 1
trap 'rm -f "$address_file" "$pid_file"' EXIT HUP INT TERM

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚪ Low · Early exits leave bus daemons

When the command is interrupted or times out, or dbus-daemon starts without printing a bus address, the trap removes the PID file without signaling the daemon; interruption skips the end-of-script kill, and the missing-address path exits immediately, leaving the private bus running.

Make exit and signal cleanup read the PID and signal the daemon before removing the temporary files.

Also at src/plugin-qt/power/session/tests/run-with-private-bus.sh:63.

Prompt for AI agents
In `src/plugin-qt/power/session/tests/run-with-private-bus.sh` at line 47:

**Early exits leave bus daemons**

When the command is interrupted or times out, or `dbus-daemon` starts without printing a bus address, the trap removes the PID file without signaling the daemon; interruption skips the end-of-script `kill`, and the missing-address path exits immediately, leaving the private bus running.

Make exit and signal cleanup read the PID and signal the daemon before removing the temporary files.

Also at `src/plugin-qt/power/session/tests/run-with-private-bus.sh:63`.

1. dbus-run-session shuts its bus down by signalling dbus-daemon. On UOS
   kernels the usec LSM labels that binary deepin_unkillable_t and denies
   the signal, so dbus-run-session waits forever; the daemon also inherited
   the test runner's stdout pipe, so ctest never saw EOF and reported a
   timeout although the test itself passed in under a second.
2. Run the test through run-with-private-bus.sh instead: a dbus-daemon
   --fork on a private bus whose stdio goes to /dev/null, with best-effort
   cleanup that never turns "cannot signal the daemon" into a failure.
3. Clear LD_PRELOAD before starting the bus. Under fakeroot libfakeroot
   fakes getuid() as 0, so the client sent AUTH EXTERNAL 30 while the
   daemon checked the real uid through SO_PEERCRED and refused the
   connection, making registerObject and registerService fail in packaging.

Log: No user-visible change; the power screensaver test passes in ctest and
in the packaging test step instead of timing out or failing.

Influence:
1. Run ctest -R power-screensaver-proxy and verify it passes in well under
   a second rather than timing out at 20 s.
2. Run the packaging step under fakeroot (dh_auto_test) and verify the test
   passes instead of failing in registerObject.
3. Run the whole suite and verify 15/15 pass with a total time of a few
   seconds.

test: 屏保总线测试不再依赖 dbus-run-session

1. dbus-run-session 靠给 dbus-daemon 发信号来关停总线。UOS 内核的 usec
   模块把该二进制标为 deepin_unkillable_t 并拒绝该信号,于是它永久等待;
   该 daemon 又继承了测试运行器的 stdout 管道,ctest 收不到 EOF,只能报
   超时——而用例本身不到一秒就已通过。
2. 改用 run-with-private-bus.sh 运行:私有总线上以 --fork 启动
   dbus-daemon,标准流全部接 /dev/null,清理尽力而为,绝不把"杀不掉
   daemon"升级成测试失败。
3. 启动总线前清空 LD_PRELOAD。fakeroot 下 libfakeroot 把 getuid() 伪装成
   0,客户端据此发 AUTH EXTERNAL 30,而 daemon 用 SO_PEERCRED 取真实 uid
   校验后拒绝连接,导致打包时 registerObject / registerService 失败。

Log: 无用户可见变化;屏保用例在 ctest 与打包测试步骤中均通过,不再超时
或失败。

Influence:
1. 执行 ctest -R power-screensaver-proxy,确认秒级通过而非 20 秒超时。
2. 在 fakeroot 下执行打包测试步骤(dh_auto_test),确认用例通过而非在
   registerObject 处失败。
3. 执行全量 ctest,确认 15/15 通过且总耗时数秒。
@fly602
fly602 force-pushed the fix/power-screensaver-test-bus branch from de75ad6 to 3542efd Compare October 15, 2026 12:41
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 100 分 (通过阈值: 70分)

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 总体评分 100 分,大于 70 分通过阈值,代码质量符合要求。本次变更修复了 power-screensaver D-Bus 测试在 UOS 内核下的超时挂起问题,代码实现清晰、注释详尽、安全合规。

🔍 详细分析

1. 语法逻辑 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: 语法正确,逻辑清晰。Shell 脚本使用 set -u 检测未定义变量,trap 确保资源清理,参数校验完整,退出状态正确传播。CMakeLists.txt 语法正确,find_program 使用 REQUIRED 确保依赖检查。


2. 代码质量 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: 代码结构清晰,注释完整。脚本头部注释详尽解释了使用 dbus-daemon 替代 dbus-run-session 的原因(usec LSM 信号拒绝、fakeroot LD_PRELOAD 认证问题),CMakeLists.txt 中也添加了对应说明。SPDX 许可证头部齐全。


3. 代码性能 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: 性能良好,资源使用合理。dbus-daemon 以 --fork 模式启动,stdio 重定向到 /dev/null 避免管道阻塞。临时文件通过 trap 清理。最佳努力清理策略合理,LSM 拒绝信号时不影响测试结果。


4. 代码安全 🔒

评价: 优秀 ✅ 通过

🔐 发现 0 个安全漏洞

安全漏洞详情:
✅ 未发现安全漏洞

建议: 存在0个安全漏洞。所有变量使用双引号包裹防止分词和通配符展开,临时文件使用 mktemp 安全创建,trap 确保清理,无命令注入风险(使用 $"@" 传递参数),无硬编码密钥或敏感信息。


💡 改进建议代码示例

# 当前代码已无需改进,以下为代码审查确认的最佳实践示例:

# 1. 安全的临时文件创建与清理
address_file=$(mktemp) || exit 1
pid_file=$(mktemp) || exit 1
trap 'rm -f "$address_file" "$pid_file"' EXIT HUP INT TERM

# 2. 正确的退出状态传播
"$@"
status=$?
# ... cleanup ...
exit $status

# 3. 最佳努力清理(不影响测试结果)
if [ -n "$daemon_pid" ]; then
    kill "$daemon_pid" 2>/dev/null || :
fi

本报告由 AI 代码审查工具自动生成

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: fly602, mhduiy

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

@fly602

fly602 commented Oct 15, 2026

Copy link
Copy Markdown
Contributor Author

/forcemerge

@deepin-bot

deepin-bot Bot commented Oct 15, 2026

Copy link
Copy Markdown

This pr force merged! (status: blocked)

@deepin-bot
deepin-bot Bot merged commit c34756c into linuxdeepin:master Oct 15, 2026
6 checks passed
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.

3 participants