Skip to content

fix: vt user lookup to prefer real user sessions over greeter entries - #93

Merged
Groveer merged 1 commit into
linuxdeepin:masterfrom
zorowk:fix349759
May 28, 2026
Merged

Groveer merged 1 commit into
linuxdeepin:masterfrom
zorowk:fix349759

Conversation

@zorowk

@zorowk zorowk commented May 26, 2026

Copy link
Copy Markdown

pms: BUG-349759
log: vt user lookup to prefer real user sessions over greeter entries

findUserByVt() 的作用,是把当前活动 VT 反查成“这个 VT 上应该对应谁”。
原来的问题是,同一个 VT 上可能同时存在两类会话记录:

  • dde 的 greeter 占位会话

  • 用户真实登录后的会话,比如 uos

如果代码只是按 VTNr 先找到第一条记录就返回,就可能先返回 dde。这样在 VT 切换回图形界面时,后端会误以为当前应该激活 greeter,而不是用户会话,最后就会把 switchToUser("dde") 发出去,导致 greeter

状态和真实用户状态错位。

这个提交的原理就是两步:

  1. 同一个 VT 上,先找真实用户会话,跳过 dde

  2. 如果没有真实用户会话,再退回到 dde

同一个 VT 上残留了多个 session 记录,而代码错误地把 greeter session 当成了当前用户 session。

@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.

Sorry @zorowk, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

pms: BUG-349759
log: vt user lookup to prefer real user sessions over greeter entries
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

你好!我是CodeGeeX。我已仔细审查了你提供的 git diff 代码。本次修改的主要目的是在查找 VT(虚拟终端)对应的用户时,优先返回普通用户会话,如果只有 Greeter(登录界面)会话,则退而求其次返回 Greeter 用户。

整体来看,代码的容错性有所提升,但存在一个严重的逻辑缺陷,以及在代码质量和性能上的可优化空间。以下是详细的审查意见:

1. 语法与逻辑 (严重缺陷)

问题:greeterUser 变量被无条件覆盖,导致逻辑失效
在当前的 for 循环中,如果匹配到 vtnr 且 session->User() == greeterUser,代码进入了 else 分支并执行 greeterUser = session->User();。
由于前置条件已经判断了 session->User() == greeterUser,这行代码实际上是在做 greeterUser = "dde" 的无用功。更严重的是,如果同一个 VT 下存在多个会话,且普通用户会话排在 Greeter 会话之后,前面的普通用户会被忽略,而 Greeter 会话会覆盖掉之前的查找结果。

推测真实意图与修复方案:
你的意图应该是:如果找到普通用户,直接返回;如果只找到 Greeter 用户,先记录下来,等循环结束后再返回。
因此,else 分支不仅多余,而且破坏了逻辑。应该直接删除 else 分支。如果后续 Greeter 的用户名可能会变,应该用一个单独的变量(如 foundGreeterUser)来保存匹配到的 Greeter 用户,而不是去覆盖初始的 greeterUser。

2. 代码性能

问题:循环内频繁构造和比较 QString
QStringLiteral("dde") 在编译期会构造一个静态的 QString,这很好。但在循环内部,每次迭代都执行 session->User() != greeterUser,这会触发 QString 的深比较,有一定开销。
改进意见: 如果 m_sessions 列表很大,可以考虑将 greeterUser 的比较逻辑优化。但鉴于通常 VT 数量和会话数量极少,这属于微优化,当前性能影响可忽略不计。保持代码简洁即可。

3. 代码质量

问题:魔法字符串
QStringLiteral("dde") 是一个硬编码的魔法字符串。如果 Greeter 用户名未来发生变更(比如变成 lightdm 等),需要在业务代码中寻找并修改,容易遗漏。
改进意见: 建议将其提取为类的常量、枚举或配置项。

问题:日志输出位置
在找到普通用户时,直接 return session->User(); 前打印了日志,这没问题。但在返回 greeterUser 时,日志打印在循环外,这也是合理的。不过,如果最终返回空,使用了 qWarning,级别合理。

4. 代码安全

问题:空指针解引用风险已修复
原代码 for (auto session : m_sessions) 存在按值拷贝的风险,且没有检查 session 是否为空。新代码修改为 for (const auto& session : m_sessions) 并增加了 if (!session) continue;,这是一个非常好的改进,避免了潜在的空指针解引用崩溃,也提升了性能(避免了拷贝)。


💡 改进后的代码建议

基于以上分析,我为你重构了这部分代码,修复了核心逻辑缺陷,并提升了代码可读性:

const QString DisplayManager::findUserByVt(int vtnr) {
    // 建议将 "dde" 提取为类成员或静态常量,避免魔法字符串
    static const QString GREETER_USER = QStringLiteral("dde");
    QString matchedGreeterUser;

    for (const auto& session : m_sessions) {
        // 防止空指针
        if (!session) {
            continue;
        }

        if (vtnr == session->VTNr()) {
            // 优先选择非 Greeter 用户
            if (session->User() != GREETER_USER) {
                qDebug() << "[DisplayManager] findUserByVt selected user session vtnr="
                         << vtnr << " user=" << session->User();
                return session->User();
            } 
            // 如果是 Greeter 用户,先记录下来,不立即返回,继续寻找是否有普通用户
            else {
                matchedGreeterUser = session->User();
            }
        }
    }

    // 循环结束后,如果没有找到普通用户,但找到了 Greeter 用户,则返回 Greeter
    if (!matchedGreeterUser.isEmpty()) {
        qDebug() << "[DisplayManager] findUserByVt selected greeter session vtnr="
                 << vtnr << " user=" << matchedGreeterUser;
        return matchedGreeterUser;
    }

    qWarning() << "[DisplayManager] findUserByVt found no session for vtnr=" << vtnr;
    return QString();
}

主要改动说明:

  1. 修复逻辑 Bug:将 else 分支中的 greeterUser = session->User(); 赋值给一个新的局部变量 matchedGreeterUser。这样确保了:只要在同一 VT 下找到了普通用户,就一定会优先返回;如果没有普通用户,才会返回记录的 matchedGreeterUser。
  2. 消除魔法字符串:将 "dde" 提取为函数内的 static const QString GREETER_USER,既保证了性能(只初始化一次),又提高了可维护性。
  3. 保留优秀改进:保留了 const auto& 引用遍历和 !session 的空指针检查。

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: justforlxz, zorowk

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

@Groveer
Groveer merged commit 38005b6 into linuxdeepin:master May 28, 2026
10 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.

4 participants