Skip to content

Conversation

@calsys456
Copy link
Contributor

@calsys456 calsys456 commented Nov 24, 2025

ddm should ack with switchToUser when treeland send an identify-only request. Lacking this acknowledgement will cause Xwayland not work after crash recover and user switch, which is a bug caused by previous commit.

Summary by Sourcery

Bug Fixes:

  • Fix Xwayland failing to start after crash recovery and user switch by acknowledging identify-only authentication flows and activating the corresponding login session.

@deepin-ci-robot
Copy link

Hi @calsys456. Thanks for your PR.

I'm waiting for a linuxdeepin member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@sourcery-ai
Copy link

sourcery-ai bot commented Nov 24, 2025

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Ensures identify-only authentication flows properly acknowledge successful login and activate the correct XDG session, fixing Xwayland failures after crash recovery and user switching, and simplifies session activation to rely directly on the provided xdgSessionId instead of reusing Auth objects.

Sequence diagram for the identify-only login and session activation flow

sequenceDiagram
    actor User as "User"
    participant Treeland as "Treeland Compositor"
    participant Display as "DDM Display"
    participant Server as "SingleWaylandDisplayServer"
    participant Logind as "Logind Manager (logind1)"

    "User" ->> "Treeland Compositor": "Initiate login (identify-only)"
    "Treeland Compositor" ->> "DDM Display": "Authenticate request (identify-only)"
    "DDM Display" -->> "Treeland Compositor": "Authentication succeeded (identify-only)"

    note over Display: "Display handles auth success for identify-only"
    "DDM Display" ->> "SingleWaylandDisplayServer": "onLoginSucceeded(user)"
    "DDM Display" ->> "DDM Display": "Lookup xdgSessionId for user in m_auths"
    "DDM Display" ->> "DDM Display": "switchToUser(user, xdgSessionId)"

    note over Display: "switchToUser now requires valid xdgSessionId and no longer relies on Auth instance"
    "DDM Display" ->> "SingleWaylandDisplayServer": "activateUser(user, xdgSessionId)"
    alt "Logind available"
        "DDM Display" ->> "Logind Manager (logind1)": "ActivateSession(QString::number(xdgSessionId))"
        "Logind Manager (logind1)" -->> "DDM Display": "Session activated"
    else "Logind not available"
        "DDM Display" -->> "DDM Display": "Skip system session activation"
    end

    "SingleWaylandDisplayServer" -->> "Treeland Compositor": "Wayland/Xwayland session ready for user"
Loading

Updated class diagram for Display, Auth, and SingleWaylandDisplayServer session handling

classDiagram
    class Display {
        - m_auths : QList< Auth* >
        - m_displayServer : DisplayServer*
        + switchToUser(user : QString, xdgSessionId : int) : void
        + onAuthSucceeded(auth : Auth*) : void
    }

    class Auth {
        + user() : QString
        + xdgSessionId() : int
        + identifyOnly() : bool
        + isSingleMode() : bool
        + sessionId() : QString
    }

    class DisplayServer {
        <<interface>>
        + stopped()
    }

    class SingleWaylandDisplayServer {
        + onLoginSucceeded(user : QString) : void
        + activateUser(user : QString, xdgSessionId : int) : void
    }

    class Logind {
        <<static_helper>>
        + isAvailable() : bool
        + serviceName() : QString
        + managerPath() : QString
    }

    class OrgFreedesktopLogin1ManagerInterface {
        + OrgFreedesktopLogin1ManagerInterface(serviceName : QString, managerPath : QString, bus : QDBusConnection)
        + ActivateSession(sessionId : QString) : void
    }

    DisplayServer <|.. SingleWaylandDisplayServer : "inherits"
    Display --> Auth : "maintains m_auths"
    Display --> DisplayServer : "uses m_displayServer"
    Display ..> SingleWaylandDisplayServer : "casts to control single-user session"
    Display ..> Logind : "checks availability and metadata"
    Display ..> OrgFreedesktopLogin1ManagerInterface : "activates session via D-Bus"

    %% Highlight identify-only flow responsibility
    Display ..> Auth : "reads identifyOnly() and xdgSessionId()"
Loading

File-Level Changes

Change Details Files
Use the provided xdgSessionId directly for user/session activation instead of looking up an Auth object
  • Remove the search through m_auths for an Auth instance matching the user before switching users
  • Assert that xdgSessionId is valid (> 0) when switching users
  • Pass xdgSessionId directly to the display server’s activateUser call
  • Use the same xdgSessionId value when calling Logind’s ActivateSession via DBus
src/daemon/Display.cpp
Properly handle identify-only authentication by acknowledging login and switching to the user/session so Xwayland continues working
  • On identify-only auth success, notify SingleWaylandDisplayServer via onLoginSucceeded(user)
  • Derive a valid xdgSessionId for the user by scanning m_auths and picking the first positive session id
  • Invoke switchToUser(user, xdgSessionId) for identify-only flows to mirror full login behavior
  • Change control flow so identify-only no longer early-returns before display server shutdown logic
src/daemon/Display.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 there - I've reviewed your changes - here's some feedback:

  • In switchToUser, relying on Q_ASSERT(xdgSessionId > 0) may cause crashes in release builds with invalid input; consider gracefully handling a non-positive xdgSessionId (e.g., early return or logging) instead of asserting.
  • In the identifyOnly branch, the inner for-loop reuses the name 'auth' and shadows the outer pointer, which makes the logic harder to follow; use a different loop variable name to improve readability.
  • The TODO about multiple sessions for a user suggests potential ambiguity in which xdgSessionId is chosen; if feasible, clarify selection strategy or pass the exact session ID from the caller to avoid relying on the first matching auth.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In switchToUser, relying on Q_ASSERT(xdgSessionId > 0) may cause crashes in release builds with invalid input; consider gracefully handling a non-positive xdgSessionId (e.g., early return or logging) instead of asserting.
- In the identifyOnly branch, the inner for-loop reuses the name 'auth' and shadows the outer pointer, which makes the logic harder to follow; use a different loop variable name to improve readability.
- The TODO about multiple sessions for a user suggests potential ambiguity in which xdgSessionId is chosen; if feasible, clarify selection strategy or pass the exact session ID from the caller to avoid relying on the first matching auth.

## Individual Comments

### Comment 1
<location> `src/daemon/Display.cpp:228-235` </location>
<code_context>
-        if (!auth) {
-            return;
-        }
+        Q_ASSERT(xdgSessionId > 0);

         auto* server = reinterpret_cast<SingleWaylandDisplayServer*>(m_displayServer);
         server->activateUser(user, xdgSessionId);

         if (Logind::isAvailable()) {
             OrgFreedesktopLogin1ManagerInterface manager(Logind::serviceName(), Logind::managerPath(), QDBusConnection::systemBus());
-            manager.ActivateSession(QString::number(auth->xdgSessionId()));
+            manager.ActivateSession(QString::number(xdgSessionId));
         }
     }
</code_context>

<issue_to_address>
**issue (bug_risk):** Relying solely on Q_ASSERT for xdgSessionId validity can cause issues in release builds.

Previously, missing Auth prevented calling ActivateSession with an invalid session id. Now that this check is gone and we only assert on xdgSessionId, release builds may call activateUser/ActivateSession with xdgSessionId <= 0 if something goes wrong upstream (e.g., DBus race, misconfiguration). Please add a runtime check (e.g., early return when xdgSessionId <= 0) in addition to the Q_ASSERT so release builds fail safely instead of using a bad session id.
</issue_to_address>

### Comment 2
<location> `src/daemon/Display.cpp:629-638` </location>
<code_context>
             stateConfig.save();

-            if (auth->isSingleMode()) {
+            if (auth->identifyOnly()) {
+                auto* server = reinterpret_cast<SingleWaylandDisplayServer*>(m_displayServer);
+                server->onLoginSucceeded(user);
+                // TODO: Use exact ID when there're multiple sessions for a user
+                int xdgSessionId = 0;
+                for (auto *auth : m_auths)
+                    if (auth->user() == user && auth->xdgSessionId() > 0) {
+                        xdgSessionId = auth->xdgSessionId();
+                        break;
+                    }
+                switchToUser(user, xdgSessionId);
+            } else if (auth->isSingleMode()) {
                 auto* server = reinterpret_cast<SingleWaylandDisplayServer*>(m_displayServer);
</code_context>

<issue_to_address>
**issue:** identifyOnly path can call switchToUser with xdgSessionId still 0 if no matching session is found.

Here xdgSessionId may stay 0 if no auth in m_auths matches the user and has xdgSessionId() > 0, yet we still call switchToUser(user, xdgSessionId). With the new Q_ASSERT(xdgSessionId > 0) this will assert in debug builds and still pass 0 in release builds. Please either guard the call (e.g. skip or handle as error if xdgSessionId <= 0) or ensure identifyOnly is only used when a valid session id is guaranteed.
</issue_to_address>

### Comment 3
<location> `src/daemon/Display.cpp:632-638` </location>
<code_context>
+                auto* server = reinterpret_cast<SingleWaylandDisplayServer*>(m_displayServer);
+                server->onLoginSucceeded(user);
+                // TODO: Use exact ID when there're multiple sessions for a user
+                int xdgSessionId = 0;
+                for (auto *auth : m_auths)
+                    if (auth->user() == user && auth->xdgSessionId() > 0) {
+                        xdgSessionId = auth->xdgSessionId();
</code_context>

<issue_to_address>
**suggestion:** The inner loop’s `auth` variable shadows the outer `auth` parameter/pointer and can be confusing.

In the identifyOnly branch, the range-for loop reuses the name `auth` for its loop variable, shadowing the outer `auth` pointer. This works but makes the code harder to read and easier to mis-edit later. Please rename the loop variable (e.g., `candidateAuth` or `sessionAuth`) to clearly distinguish it from the outer pointer.

```suggestion
                // TODO: Use exact ID when there're multiple sessions for a user
                int xdgSessionId = 0;
                for (auto *sessionAuth : m_auths)
                    if (sessionAuth->user() == user && sessionAuth->xdgSessionId() > 0) {
                        xdgSessionId = sessionAuth->xdgSessionId();
                        break;
                    }
```
</issue_to_address>

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.

ddm should ack with switchToUser when treeland send an identify-only
request. Lacking this acknowledgement will cause Xwayland not work after
crash recover and user switch, which is a bug caused by previous commit.
@zccrs zccrs merged commit e4f122b into linuxdeepin:master Nov 27, 2025
7 of 9 checks passed
@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: calsys456, zccrs

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants