Skip to content

fix: support showing lock screen triggered by logind lock signal#197

Merged
yixinshark merged 1 commit intolinuxdeepin:masterfrom
yixinshark:fix-sessionLock
Mar 17, 2026
Merged

fix: support showing lock screen triggered by logind lock signal#197
yixinshark merged 1 commit intolinuxdeepin:masterfrom
yixinshark:fix-sessionLock

Conversation

@yixinshark
Copy link
Contributor

@yixinshark yixinshark commented Mar 17, 2026

  • Support showing the lock screen when receiving a lock signal from logind.

  • Use asynchronous DBus call for RequestLock to prevent blocking the main thread when locking the session, especially when switching TTY.

  • Introduce a boolean m_inCallRequestLock to prevent multiple concurrent lock requests from being sent in a short time.

  • 支持接收 logind 的 lock 锁定信号后,触发并显示锁屏。

  • 使用异步 DBus 调用 RequestLock,防止在锁定会话(如切换 TTY 时)阻塞主线程。

  • 引入了 m_inCallRequestLock 标志位,防止短时间内产生多次并发的锁屏请求。

Log: support showing lock screen triggered by logind lock signal
Pms: BUG-314653

Summary by Sourcery

Handle logind lock signals by asynchronously triggering the lock screen without blocking the session manager main thread.

Bug Fixes:

  • Ensure the lock screen is shown when the session is locked via logind signals, including during TTY switches.
  • Prevent main-thread blocking when requesting the lock screen by using an asynchronous DBus call instead of a synchronous one.
  • Avoid rapid duplicate lock requests by tracking in-flight lock operations with a guard flag.

- Support showing the lock screen when receiving a lock signal from logind.
- Use asynchronous DBus call for RequestLock to prevent blocking the main thread when locking the session, especially when switching TTY.
- Introduce a boolean `m_inCallRequestLock` to prevent multiple concurrent lock requests from being sent in a short time.

- 支持接收 logind 的 lock 锁定信号后,触发并显示锁屏。
- 使用异步 DBus 调用 [RequestLock](cci:1://file:///home/zyz/works/work/v25/dde-session/src/dde-session/impl/sessionmanager.cpp:418:0-434:1),防止在锁定会话(如切换 TTY 时)阻塞主线程。
- 引入了 `m_inCallRequestLock` 标志位,防止短时间内产生多次并发的锁屏请求。

Log: support showing lock screen triggered by logind lock signal
Pms: BUG-314653
@sourcery-ai
Copy link

sourcery-ai bot commented Mar 17, 2026

Reviewer's Guide

This PR changes session locking to use an asynchronous DBus call for the lock screen and wires the logind lock signal to trigger the lock, with a guard flag to avoid concurrent lock requests that can block the main thread during TTY switches.

Updated class diagram for SessionManager asynchronous lock handling

classDiagram
    class SessionManager {
        - org_freedesktop_systemd1_Manager* m_systemd1ManagerInter
        - org_freedesktop_DBus* m_DBusInter
        - QMap~uint,Inhibitor*~ m_inhibitorMap
        - bool m_inCallRequestLock
        + SessionManager(QObject* parent)
        + void RequestLock()
        + void RequestHibernate()
        + void RequestLogout()
        + void handleLoginSessionLocked()
        + void handleLoginSessionUnlocked()
    }

    class QDBusInterface {
        + QDBusInterface(QString service, QString path, QString interface, QDBusConnection connection)
        + QDBusPendingCall asyncCall(QString method)
    }

    class QDBusPendingCall {
    }

    class QDBusPendingCallWatcher {
        + QDBusPendingCallWatcher(QDBusPendingCall call, QObject* parent)
        + void finished(QDBusPendingCallWatcher* watcher)
    }

    class QDBusPendingReply {
        + bool isError()
        + QDBusError error()
    }

    class QDBusError {
        + QString message()
    }

    SessionManager --> QDBusInterface : uses
    SessionManager --> QDBusPendingCall : uses
    SessionManager --> QDBusPendingCallWatcher : creates
    SessionManager --> QDBusPendingReply : processes
    QDBusPendingReply --> QDBusError : returns
Loading

File-Level Changes

Change Details Files
Switch RequestLock from synchronous to asynchronous DBus invocation and handle async completion.
  • Replace synchronous QDBusInterface::call("Show") with asyncCall("Show") to avoid blocking the main thread.
  • Create a QDBusPendingCallWatcher for the pending call, attach a finished handler lambda, and log any DBus error on completion.
  • Reset the in-flight lock-request flag and delete the watcher in the async completion handler.
src/dde-session/impl/sessionmanager.cpp
Ensure logind lock signal triggers the lock screen without re-entrant or concurrent lock requests.
  • Add m_inCallRequestLock boolean member to track whether an async RequestLock call is in progress.
  • Initialize m_inCallRequestLock to false in the SessionManager constructor.
  • In handleLoginSessionLocked, remove direct m_locked/emitLockChanged updates and instead guard against concurrent calls using m_inCallRequestLock, then invoke RequestLock asynchronously and log debug messages.
  • Update comments in handleLoginSessionLocked to explain the need for asynchronous RequestLock when switching TTY and potential blocking behavior.
src/dde-session/impl/sessionmanager.cpp
src/dde-session/impl/sessionmanager.h

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

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • The m_inCallRequestLock flag is only cleared in the async DBus callback; if the call never finishes or the watcher is never triggered, future lock requests will be suppressed indefinitely—consider adding a timeout or a fallback path to reset the flag.
  • Currently m_inCallRequestLock is only used in handleLoginSessionLocked; if other code paths call RequestLock() directly they can still issue concurrent async calls—consider moving the flag handling into RequestLock() itself so the concurrency guard applies uniformly.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `m_inCallRequestLock` flag is only cleared in the async DBus callback; if the call never finishes or the watcher is never triggered, future lock requests will be suppressed indefinitely—consider adding a timeout or a fallback path to reset the flag.
- Currently `m_inCallRequestLock` is only used in `handleLoginSessionLocked`; if other code paths call `RequestLock()` directly they can still issue concurrent async calls—consider moving the flag handling into `RequestLock()` itself so the concurrency guard applies uniformly.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@deepin-ci-robot
Copy link

deepin pr auto review

这段代码的修改主要是将 RequestLock 方法从同步调用改为异步调用,并增加了防止重复调用的机制。这是一个很好的改进,特别是在涉及 DBus 调用时,避免阻塞主线程非常重要。以下是对这段代码的详细审查和改进建议:

1. 语法逻辑审查

  • 修改点分析

    • 引入了 QDBusPendingCallQDBusPendingCallWatcher 来支持异步 DBus 调用。
    • RequestLock 方法中,将同步的 inter.call("Show") 改为异步的 inter.asyncCall("Show"),并通过 QDBusPendingCallWatcher 监听调用结果。
    • handleLoginSessionLocked 方法中,增加了 m_inCallRequestLock 标志位,防止短时间内多次调用 RequestLock
  • 潜在问题

    • RequestLock 中,QDBusInterface 对象的创建方式从 this 作为父对象改为不设置父对象。这可能导致内存泄漏,因为 inter 没有被显式释放。
    • m_inCallRequestLock 标志位在 RequestLock 的异步回调中设置为 false,但如果 RequestLock 被多次调用(尽管有 m_inCallRequestLock 保护),可能会出现竞态条件。

2. 代码质量审查

  • 改进点

    • 使用异步调用避免了阻塞主线程,提升了用户体验。
    • 增加了防止重复调用的逻辑,避免了潜在的多次锁屏请求。
  • 建议

    • QDBusInterface 应该设置父对象或使用智能指针管理,避免内存泄漏。可以改为:
      QDBusInterface inter("org.deepin.dde.LockFront1", "/org/deepin/dde/LockFront1", "org.deepin.dde.LockFront1", QDBusConnection::sessionBus(), this);
    • RequestLock 的异步回调中,应该检查 m_inCallRequestLock 是否仍然为 true,避免异常情况下标志位未被正确重置。

3. 代码性能审查

  • 改进点

    • 异步调用避免了主线程阻塞,提升了响应速度。
    • 防止重复调用的逻辑减少了不必要的 DBus 调用。
  • 建议

    • 如果 RequestLock 被频繁调用,可以考虑使用 QDBusAbstractInterface 的静态方法或缓存 QDBusInterface 对象,减少重复创建的开销。

4. 代码安全审查

  • 潜在问题

    • m_inCallRequestLock 标志位没有使用原子操作或互斥锁保护,在多线程环境下可能会出现竞态条件。虽然 Qt 的信号槽机制通常在主线程执行,但如果有其他线程调用 RequestLock,可能会出现问题。
    • 如果 RequestLock 的异步回调因为某种原因未被触发(例如 DBus 服务崩溃),m_inCallRequestLock 可能永远不会被重置为 false,导致后续的锁屏请求被忽略。
  • 建议

    • 使用 QAtomicBoolstd::atomic<bool> 替代普通的 bool 类型,确保标志位的原子性:
      std::atomic<bool> m_inCallRequestLock{false};
    • RequestLock 的异步回调中,可以增加超时机制或错误处理逻辑,确保标志位能够被正确重置。

5. 改进后的代码示例

以下是改进后的 RequestLockhandleLoginSessionLocked 方法:

void SessionManager::RequestLock()
{
    QDBusInterface inter("org.deepin.dde.LockFront1", "/org/deepin/dde/LockFront1", "org.deepin.dde.LockFront1", QDBusConnection::sessionBus(), this);
    
    // 使用异步调用方式防止当前线程阻塞
    QDBusPendingCall async = inter.asyncCall("Show");
    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this);
    connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) {
        QDBusPendingReply<> reply = *watcher;
        if (reply.isError()) {
            qWarning() << "failed to lock, async error: " << reply.error().message();
        }
        
        // 确保标志位被正确重置
        if (m_inCallRequestLock) {
            m_inCallRequestLock = false;
        }
        watcher->deleteLater();
    });
}

void SessionManager::handleLoginSessionLocked()
{
    qDebug() << "login session locked." << locked();
    // 在特殊情况下,比如用 dde-switchtogreeter 命令切换到 greeter, 即切换到其他 tty
    // 此时同步的 DBus RequestLock 方法不能立即返回,需要使用异步调用避免阻塞主线程。

    // 如果已经锁定,则立即返回
    if (locked()) {
        qDebug() << "already locked, return";
        return;
    }

    // 防止短时间内多次同时调用 RequestLock
    if (m_inCallRequestLock) {
        qDebug() << "handleLoginSessionLocked inCall is true, return";
        return;
    }
    
    m_inCallRequestLock = true;
    
    qDebug() << "handleLoginSessionLocked call RequestLock begin (async)";
    RequestLock();
}

6. 头文件修改建议

sessionmanager.h 中,将 m_inCallRequestLock 的类型改为 std::atomic<bool>

#include <atomic>

class SessionManager : public QObject
{
    // ... 其他代码 ...
private:
    std::atomic<bool> m_inCallRequestLock{false};
    // ... 其他代码 ...
};

总结

这段代码的修改方向是正确的,但需要进一步完善以确保内存安全和线程安全。通过使用 std::atomic<bool> 和改进 QDBusInterface 的生命周期管理,可以进一步提升代码的健壮性。

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: robertkill, yixinshark

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

@yixinshark yixinshark merged commit 904b4fa into linuxdeepin:master Mar 17, 2026
18 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