From 3542efdd7d6e9ba9812cc73c797c1e48206d535f Mon Sep 17 00:00:00 2001 From: fuleyi Date: Wed, 14 Oct 2026 14:31:04 +0800 Subject: [PATCH] test: run the screensaver bus test without dbus-run-session MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 通过且总耗时数秒。 --- .../power/session/tests/CMakeLists.txt | 13 +++- .../session/tests/run-with-private-bus.sh | 77 +++++++++++++++++++ 2 files changed, 86 insertions(+), 4 deletions(-) create mode 100755 src/plugin-qt/power/session/tests/run-with-private-bus.sh diff --git a/src/plugin-qt/power/session/tests/CMakeLists.txt b/src/plugin-qt/power/session/tests/CMakeLists.txt index 65c09ad5..1879f938 100644 --- a/src/plugin-qt/power/session/tests/CMakeLists.txt +++ b/src/plugin-qt/power/session/tests/CMakeLists.txt @@ -2,7 +2,7 @@ # SPDX-License-Identifier: LGPL-3.0-or-later find_package(Qt6 REQUIRED COMPONENTS Test) -find_program(DBUS_RUN_SESSION dbus-run-session REQUIRED) +find_program(DBUS_DAEMON dbus-daemon REQUIRED) add_executable(tst-screensaverproxy tst-screensaverproxy.cpp @@ -11,7 +11,12 @@ add_executable(tst-screensaverproxy ) target_include_directories(tst-screensaverproxy PRIVATE ..) target_link_libraries(tst-screensaverproxy PRIVATE Qt6::Test Qt6::DBus Dtk6::Core) + +# run-with-private-bus.sh, not dbus-run-session: the usec LSM denies signals to +# dbus-daemon, which would make dbus-run-session hang and the test time out. add_test(NAME power-screensaver-proxy - COMMAND ${DBUS_RUN_SESSION} --config-file=${CMAKE_CURRENT_SOURCE_DIR}/session.conf - -- $) -set_tests_properties(power-screensaver-proxy PROPERTIES TIMEOUT 20) + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/run-with-private-bus.sh + ${CMAKE_CURRENT_SOURCE_DIR}/session.conf + $) +set_tests_properties(power-screensaver-proxy PROPERTIES TIMEOUT 20 + ENVIRONMENT "DBUS_DAEMON_BIN=${DBUS_DAEMON}") diff --git a/src/plugin-qt/power/session/tests/run-with-private-bus.sh b/src/plugin-qt/power/session/tests/run-with-private-bus.sh new file mode 100755 index 00000000..b7960a81 --- /dev/null +++ b/src/plugin-qt/power/session/tests/run-with-private-bus.sh @@ -0,0 +1,77 @@ +#!/bin/sh +# SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +# +# SPDX-License-Identifier: LGPL-3.0-or-later +# +# Run a command against a freshly started private session bus. +# +# Do not use dbus-run-session here. It terminates the bus by signalling +# dbus-daemon, and UOS kernels with the usec LSM label /usr/bin/dbus-daemon as +# deepin_unkillable_t, so that signal is denied: +# +# uavc: denied { signal } for comm="dbus-run-sessio" +# scontext=...:deepin_usec_t tcontext=...:deepin_unkillable_t +# +# dbus-run-session then waits forever for its daemon. That daemon also inherits +# the stdout pipe of the test runner, so ctest never sees EOF and reports a +# timeout even though the test itself finished and passed. Starting the daemon +# with --fork avoids depending on a signal at all: cleanup below is best effort, +# and an unreapable daemon only costs a little idle memory. +# +# Under fakeroot (dpkg-buildpackage) libfakeroot is injected through LD_PRELOAD +# and fakes getuid() as root. The client then authenticates with "AUTH EXTERNAL +# 30" while the daemon checks the real uid 10759 via SO_PEERCRED and refuses the +# connection, so every registerObject/registerService call fails. The intercept +# library is of no use to this test, so drop it and restore the real uid. +LD_PRELOAD= +export LD_PRELOAD + +set -u + +if [ $# -lt 2 ]; then + echo "usage: $0 [args...]" >&2 + exit 2 +fi + +bus_config=$1 +shift +dbus_daemon=${DBUS_DAEMON_BIN:-dbus-daemon} + +command -v "$dbus_daemon" >/dev/null 2>&1 || { + echo "$0: dbus-daemon not found (looked for '$dbus_daemon')" >&2 + exit 1 +} + +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 +# must never hold a pipe of the test runner open. +"$dbus_daemon" --config-file="$bus_config" --fork \ + --print-address=3 --print-pid=4 \ + 3>"$address_file" 4>"$pid_file" /dev/null 2>&1 || { + echo "$0: cannot start $dbus_daemon with $bus_config" >&2 + exit 1 +} + +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 +export DBUS_SESSION_BUS_ADDRESS + +"$@" +status=$? + +# Best effort only: where the LSM allows it the daemon is reaped, where it does +# not the failure to signal must not turn a passing test into a failing one. +if [ -n "$daemon_pid" ]; then + kill "$daemon_pid" 2>/dev/null || : +fi + +exit $status