Skip to content

Conversation

@calsys456
Copy link
Collaborator

@calsys456 calsys456 commented Dec 31, 2025

The use of org.freedesktop.login1.Session User property is incorrect, what we exactly need is the Name property. Correct this.

Btw, trying to mark already logged in logind sessions as logged-in in treeland is incorrect, remove this part of code.

Summary by Sourcery

Correct user session handling with logind to fix unlock issues after lockscreen.

Bug Fixes:

  • Use the logind session Name property instead of User to resolve incorrect username mapping when updating login state.
  • Avoid redundantly marking pre-existing logind sessions as logged-in in the greeter by removing the eager ListSessions logic.

Enhancements:

  • Simplify asynchronous UI updates by replacing DThreadUtils usage with direct QMetaObject::invokeMethod for updating user login state.

The use of org.freedesktop.login1.Session User property is incorrect,
what we exactly need is the Name property. Correct this.

Btw, trying to mark already logged in logind sessions as logged-in in
treeland is incorrect, remove this part of code.
@sourcery-ai
Copy link

sourcery-ai bot commented Dec 31, 2025

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Corrects how the greeter identifies users from logind sessions and simplifies session state handling, ensuring user login state updates use the session Name property and are dispatched back to the GUI thread without pre-marking existing sessions as logged-in.

Sequence diagram for updated user login state handling

sequenceDiagram
    participant Logind as LogindSession
    participant GreeterProxy as GreeterProxy
    participant ThreadPool as QThreadPool
    participant SessionIF as Login1SessionInterface
    participant GuiThread as GuiThread
    participant UserModel as UserModel

    Logind ->> GreeterProxy: SessionNew/SessionRemoved
    GreeterProxy ->> ThreadPool: start(updateUserLoginState path, loggedIn)
    ThreadPool ->> SessionIF: create(path)
    ThreadPool ->> SessionIF: name()
    SessionIF -->> ThreadPool: username
    ThreadPool ->> GuiThread: QMetaObject::invokeMethod(username, loggedIn)
    GuiThread ->> GreeterProxy: lambda(username, loggedIn)
    GreeterProxy ->> UserModel: updateUserLoginState(username, loggedIn)
    GreeterProxy ->> GreeterProxy: updateLocketState()
Loading

Class diagram for updated GreeterProxy session handling

classDiagram
    class GreeterProxy {
        +GreeterProxy()
        +void init()
        +void login(QString user, QString password, int sessionIndex)
        +void error()
        +void updateUserLoginState(QDBusObjectPath path, bool loggedIn)
        +UserModel* userModel()
        +void updateLocketState()
    }

    class UserModel {
        +UserModel()
        +void updateUserLoginState(QString username, bool loggedIn)
    }

    class OrgFreedesktopLogin1SessionInterface {
        +OrgFreedesktopLogin1SessionInterface(QString serviceName, QString path, QDBusConnection connection)
        +QString name()
    }

    class QThreadPool {
        +static QThreadPool* globalInstance()
        +void start(std::function<void()> task)
    }

    class QMetaObject {
        +static bool invokeMethod(QObject* object, std::function<void()> method)
    }

    GreeterProxy --> UserModel : uses
    GreeterProxy --> OrgFreedesktopLogin1SessionInterface : queries_session_name
    GreeterProxy --> QThreadPool : schedules_background_task
    GreeterProxy --> QMetaObject : dispatches_to_gui_thread
Loading

File-Level Changes

Change Details Files
Fix how user identity is resolved from logind sessions and ensure UI updates are dispatched correctly to the main thread.
  • Replace use of the login1 Session.User property and getpwuid() lookup with the Session.Name property to derive the username directly from the session
  • Replace DThreadUtils::gui().run() with QMetaObject::invokeMethod() to marshal user login state updates back onto the GUI thread
  • Tighten QThreadPool::globalInstance() usage spacing for consistency
src/greeter/greeterproxy.cpp
Remove incorrect logic that pre-marks already existing logind sessions as logged-in in the greeter.
  • Remove asynchronous startup code that listed all logind sessions via ListSessions() and called onSessionNew() for each existing session
  • Drop the now-unused DThreadUtils include since the related code path was removed
src/greeter/greeterproxy.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

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 lambda passed to QThreadPool::globalInstance()->start still captures this without any lifetime guard; consider using a QPointer<GreeterProxy> or moving the DBus call to the main thread to avoid accessing a destroyed object.
  • When switching to session.name() as the username source, it may be worth handling the case where name() is empty or the DBus call fails, so that updateUserLoginState doesn’t silently act on an invalid username.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The lambda passed to QThreadPool::globalInstance()->start still captures `this` without any lifetime guard; consider using a `QPointer<GreeterProxy>` or moving the DBus call to the main thread to avoid accessing a destroyed object.
- When switching to `session.name()` as the username source, it may be worth handling the case where `name()` is empty or the DBus call fails, so that `updateUserLoginState` doesn’t silently act on an invalid username.

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.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a critical bug preventing users from unlocking the screen after lockscreen. The fix corrects the logind session property usage and simplifies session tracking logic.

  • Replaces incorrect User property with correct Name property when retrieving username from logind sessions
  • Removes redundant eager initialization code that incorrectly marked pre-existing sessions as logged-in
  • Simplifies asynchronous UI updates by replacing DThreadUtils with QMetaObject::invokeMethod

void GreeterProxy::updateUserLoginState(const QDBusObjectPath &path, bool loggedIn)
{
QThreadPool ::globalInstance()->start([this, path, loggedIn] {
QThreadPool::globalInstance()->start([this, path, loggedIn] {
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

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

Missing include for QThreadPool. The code uses QThreadPool::globalInstance() but does not include the necessary header. Add #include <QThreadPool> to the includes section to ensure proper compilation.

缺少 QThreadPool 的头文件包含。代码使用了 QThreadPool::globalInstance() 但没有包含必要的头文件。请在包含部分添加 #include <QThreadPool> 以确保正确编译。

Copilot uses AI. Check for mistakes.
QDBusConnection ::systemBus());
QString username = QString::fromLocal8Bit(getpwuid(session.user().userId)->pw_name);
DThreadUtils::gui().run(this, [this, username, loggedIn]() {
QString username = session.name();
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

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

Missing error handling for DBus property access. The call to session.name() may fail or return an empty/invalid value if the DBus session object is invalid or the Name property cannot be retrieved. Consider checking if the returned username is valid before invoking the GUI update, or handle potential DBus errors to prevent unexpected behavior.

缺少对 DBus 属性访问的错误处理。如果 DBus 会话对象无效或无法检索 Name 属性,对 session.name() 的调用可能会失败或返回空/无效值。建议在调用 GUI 更新之前检查返回的用户名是否有效,或处理潜在的 DBus 错误以防止意外行为。

Suggested change
QString username = session.name();
if (!session.isValid()) {
qCWarning(treelandGreeter) << "Failed to create logind session interface for path"
<< path.path();
return;
}
const QString username = session.name();
if (username.isEmpty()) {
qCWarning(treelandGreeter) << "Received empty username from logind session for path"
<< path.path();
return;
}

Copilot uses AI. Check for mistakes.
Comment on lines 294 to 302
QThreadPool::globalInstance()->start([this, path, loggedIn] {
OrgFreedesktopLogin1SessionInterface session(Logind::serviceName(),
path.path(),
QDBusConnection ::systemBus());
QString username = QString::fromLocal8Bit(getpwuid(session.user().userId)->pw_name);
DThreadUtils::gui().run(this, [this, username, loggedIn]() {
QString username = session.name();
QMetaObject::invokeMethod(this, [this, username, loggedIn]() {
userModel()->updateUserLoginState(username, loggedIn);
updateLocketState();
});
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

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

Potential lifetime issue with lambda capture. The lambda captures this in both the thread pool task and the inner QMetaObject::invokeMethod call. If the GreeterProxy object is destroyed before these lambdas execute, accessing this will lead to undefined behavior. Consider using QPointer or adding lifetime guards to ensure the object is still valid when the callbacks execute.

Lambda 捕获可能存在生命周期问题。Lambda 在线程池任务和内部的 QMetaObject::invokeMethod 调用中都捕获了 this。如果 GreeterProxy 对象在这些 lambda 执行之前被销毁,访问 this 将导致未定义行为。建议使用 QPointer 或添加生命周期保护以确保回调执行时对象仍然有效。

Copilot uses AI. Check for mistakes.
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.

1 participant