Skip to content

fix(daemon): identify active desktop session by UID instead of username - #788

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:release/v20from
pppanghu77:release/v20
Sep 20, 2026
Merged

deepin-bot[bot] merged 1 commit into
linuxdeepin:release/v20from
pppanghu77:release/v20

Conversation

@pppanghu77

@pppanghu77 pppanghu77 commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

问题 / Problem

域账号环境下 dde-cooperation-daemon 启动即退出,日志报 exit, inactive desktop session,跨端协同功能不可用。

域账号场景下 loginctl 会话用户名与家目录名可能不一致(如会话用户 TM189295、家目录 @TM189295),原实现将两者做字符串比对,比对失败即误判为非活动桌面会话。

修复 / Fix

参照 0.8.9 版本包的实现思路,改用 UID 判定活动会话:

  • isActiveUser() 解析 loginctl list-sessions 时同时记录会话 UID,最终以「活动会话 UID == getuid()」判定,与用户命名体系解耦;
  • KEY_CURRENT_ACTIVE_USER 属性改存活动会话 UID,日志同步输出 active uid / current uid;
  • ServiceManager 运行时活动用户检查同步改为 UID 比对,保持语义一致。

自测 / Test

  • 编译通过(dde-cooperation-daemon + daemon-core);
  • 本机(用户名 ut005189、家目录 /home/ut005189@uos 不一致场景)运行新 daemon,判定通过并完整启动;
  • 置空/篡改 $HOME 模拟域账号命名异常,判定不再受影响。

Summary by Sourcery

Identify the active desktop session by the current process UID instead of comparing session and home-directory usernames.

Bug Fixes:

  • Fix daemon startup and runtime active-session detection for domain accounts whose session usernames differ from their home-directory names by matching desktop sessions by UID.

Enhancements:

  • Store and log the active desktop session UID, and use UID-based checks consistently across daemon startup and service monitoring.

@sourcery-ai

sourcery-ai Bot commented Sep 11, 2026

Copy link
Copy Markdown

Reviewer's Guide

The daemon now identifies and monitors the active desktop session by numeric UID rather than comparing loginctl usernames with the home-directory name, avoiding false inactive-session exits in domain-account environments while keeping startup and runtime checks consistent.

Sequence diagram for UID-based active desktop session validation

sequenceDiagram
    participant Daemon
    participant Loginctl
    participant OS

    Daemon->>Loginctl: list-sessions
    Loginctl-->>Daemon: session ID, UID, username, state, desktop
    Daemon->>OS: getuid()
    OS-->>Daemon: current UID
    Daemon->>Daemon: isActiveUser()
    alt active session UID equals current UID
        Daemon->>Daemon: setProperty(KEY_CURRENT_ACTIVE_USER, activeUid)
        Daemon->>Daemon: continue startup
    else UID mismatch
        Daemon->>Daemon: exit(0)
    end
Loading

Sequence diagram for runtime active-session UID monitoring

sequenceDiagram
    participant ServiceManager
    participant OS
    participant Application

    loop every 500 ms
        ServiceManager->>OS: getuid()
        OS-->>ServiceManager: current UID
        ServiceManager->>Application: property(KEY_CURRENT_ACTIVE_USER)
        Application-->>ServiceManager: active session UID
        alt active UID differs from current UID
            ServiceManager->>ServiceManager: stop timer
            ServiceManager->>Application: exit(0)
        end
    end
Loading

File-Level Changes

Change Details Files
Replace username/home-directory matching with UID-based active-session detection.
  • Parse and retain each loginctl session UID alongside its username.
  • Compare the active session UID with the process UID from getuid().
  • Store the active UID in KEY_CURRENT_ACTIVE_USER and update diagnostics to report both UIDs.
  • Apply the same UID comparison in the runtime desktop-user monitor before terminating the daemon.
src/apps/daemon/main.cpp
src/plugins/daemon/core/service/servicemanager.cpp

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

@github-actions

github-actions Bot commented Sep 11, 2026 •

Copy link
Copy Markdown

CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅

@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/apps/daemon/main.cpp" line_range="150-155" />
<code_context>
-    qApp->setProperty(KEY_CURRENT_ACTIVE_USER, username);
-    qCritical() << "active session user:" << username << " current user:" << curUser;
+    // 域账号场景下会话用户名与家目录名可能不一致(如 "@xxx"),改用 UID 比对判定活动会话
+    QString curUid = QString::number(getuid());
+    qApp->setProperty(KEY_CURRENT_ACTIVE_USER, activeUid);
+    qCritical() << "active session user:" << username << " active uid:" << activeUid << " current uid:" << curUid;
</code_context>
<issue_to_address>
**issue (bug_risk):** Windows builds fail to compile because `getuid()` is compiled after the `_WIN32` early return, while `<unistd.h>` is excluded on Windows; a runtime `return` does not remove the later code from compilation.

**Triggers:** When building the daemon on Windows.

**Suggested fix:** Guard the UID-based code with the same platform condition as the `getuid()` declaration, or provide a Windows-specific UID implementation.

```suggestion
    // 域账号场景下会话用户名与家目录名可能不一致(如 "@xxx"),改用 UID 比对判定活动会话
#ifndef _WIN32
    QString curUid = QString::number(getuid());
    qApp->setProperty(KEY_CURRENT_ACTIVE_USER, activeUid);
    qCritical() << "active session user:" << username << " active uid:" << activeUid << " current uid:" << curUid;

    return (activeUid == curUid);
#endif
```
</issue_to_address>

### Comment 2
<location path="src/apps/daemon/main.cpp" line_range="144-147" />
<code_context>
         // 判断用户状态和桌面状态
         if (isActive && isDesktopActive) {
             username = sessions.take(session);
+            activeUid = sessionUids.value(session);
         }
     }

</code_context>
<issue_to_address>
**issue (bug_risk):** When multiple desktop sessions are simultaneously active, each matching session overwrites `activeUid`, so a later active session with a different UID can replace the current user's matching UID and cause `isActiveUser()` to return false.

**Triggers:** When multiple seats or otherwise multiple active desktop sessions exist and the current user's session is not the last one in `QMap` key order.

**Suggested fix:** Evaluate each active desktop session UID against `getuid()` directly, or retain a matching UID instead of unconditionally overwriting `activeUid`.

```suggestion
        if (isActive && isDesktopActive) {
            if (sessionUids.value(session) == QString::number(getuid())) {
                username = sessions.take(session);
                activeUid = sessionUids.value(session);
            }
        }
```
</issue_to_address>

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

Comment thread src/apps/daemon/main.cpp Outdated
Comment thread src/apps/daemon/main.cpp Outdated
@pppanghu77

Copy link
Copy Markdown
Contributor Author

I have read the CLA Document and I hereby sign the CLA.

- In domain-account environments the loginctl session username may differ
  from the home directory name (e.g. "@xxx"), and the name comparison
  failed, making the daemon exit right after startup (inactive desktop session)
- isActiveUser() now compares the active desktop session UID against getuid(),
  decoupled from the user naming scheme; when multiple desktop sessions are
  active, only the one belonging to the current user is taken as the active session
- KEY_CURRENT_ACTIVE_USER now stores the active session UID and the
  ServiceManager runtime check compares UIDs accordingly
- Guard the loginctl/getuid() based session check with _WIN32 so the daemon
  still compiles on Windows, where the check is not applicable
- Update SPDX copyright year to 2023-2026 for the modified files

修复(daemon): 改用 UID 而非用户名判定活动桌面会话

- 域账号场景下 loginctl 会话用户名与家目录名可能不一致(如 "@xxx"),
  名字比对失败导致 daemon 启动即退出(exit, inactive desktop session)
- isActiveUser 改为比对活动桌面会话 UID 与 getuid(), 与命名体系解耦;
  存在多个活跃桌面会话时, 以属于当前用户的会话为准
- KEY_CURRENT_ACTIVE_USER 改存活动会话 UID, ServiceManager 运行时检查同步按 UID 判定
- 活动会话检查增加 _WIN32 平台守卫, 修复 Windows 构建下 getuid() 编译失败的问题
- 更新所改文件的 SPDX 版权年份为 2023-2026

Log: 修复域账号环境下跨端协同 daemon 无法启动的问题
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

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

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 未发现安全问题,代码逻辑正确,修复方案合理。将活动桌面会话识别方式从用户名比对改为 UID 比对,有效解决域账号场景下用户名与家目录名不一致的问题。

🔍 详细分析

1. 语法逻辑 ✅

评价: 优秀 ✅ 通过

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

建议: 代码语法正确,逻辑清晰。getuid() 通过 #ifndef _WIN32 条件编译正确保护,#include <unistd.h> 头文件引入位置正确。isActiveUser() 函数中新增 sessionUids 映射表和 curUid 变量,与现有 sessions 映射表逻辑一致。条件判断逻辑正确,确保多用户场景下仅匹配当前 UID 的活跃桌面会话。


2. 代码质量 ✅

评价: 优秀 ✅ 通过

潜在问题:

  1. src/apps/daemon/main.cpp:79 - isActiveUser() 函数中 #ifdef _WIN32 ... #endif 后紧接 #ifndef _WIN32,建议使用 #else 替代以提高可读性和健壮性。若中间代码出现 #undef _WIN32 会导致行为异常。
  2. src/apps/daemon/main.cpp:80 - username 变量修改后仅用于 qCritical() 日志输出,不再参与返回逻辑和属性设置(两者均改用 activeUid)。若日志被移除则成为死代码。

建议: 1.建议将 #ifndef _WIN32 改为 #else 与 #ifdef _WIN32 配对使用 2.考虑将 username 变量内联到日志语句中


3. 代码性能 ✅

评价: 优秀 ✅ 通过

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

建议: getuid() 是轻量级系统调用,性能影响可忽略。新增 sessionUids 映射表内存开销极小。无性能瓶颈。


4. 代码安全 🔒

评价: 优秀 ✅ 通过

🔐 发现 0 个安全漏洞

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

建议: 1.安全扫描工具误报 main.cpp:223 行 app.exec() 为 RCE,经审计确认为 Qt 事件循环,非远程代码执行 2.getuid() 返回内核控制 UID,不可伪造,比用户名比对更安全 3.QProcess::start() 不使用 shell,不存在命令注入风险


💡 改进建议代码示例

// 建议: 使用 #else 替代 #ifndef _WIN32
bool isActiveUser()
{
#ifdef _WIN32
    return "admin";
#else
    QString username = "";
    QString activeUid = "";
    // ... 原有逻辑 ...
    return (activeUid == curUid);
#endif
}

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

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: pppanghu77, re2zero

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

@pppanghu77

Copy link
Copy Markdown
Contributor Author

/forcemerge

@deepin-bot
deepin-bot Bot merged commit 60079db into linuxdeepin:release/v20 Sep 20, 2026
15 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