Skip to content

fix: allow treeland to start without any users - #1151

Draft
Groveer wants to merge 1 commit into
linuxdeepin:master-backup-20260717from
Groveer:agent/git-commit/bfd5931c
Draft

fix: allow treeland to start without any users#1151
Groveer wants to merge 1 commit into
linuxdeepin:master-backup-20260717from
Groveer:agent/git-commit/bfd5931c

Conversation

@Groveer

@Groveer Groveer commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Fix treeland crash when no system users exist. The compositor previously assumed the "dde" user always exists and would crash via assertion, undefined behavior, or qFatal. This PR ensures treeland can start gracefully in the absence of users.

Changes

  1. session.cpp: fall back to getpwuid(getuid()) when getpwnam("dde") fails in ensureSession, ensuring globalSession() is never null
  2. usermodel.cpp: guard empty user list before calling .first() to avoid undefined behavior
  3. usermodel.cpp: replace qFatal with qCWarning + early return for graceful D-Bus degradation (Accounts service unavailable)
  4. treeland.cpp: replace Q_ASSERT(globalSession) with a runtime null check

Related: WM-82

Summary by Sourcery

Ensure Treeland starts and degrades gracefully when no system users or global session are available.

Bug Fixes:

  • Avoid crashing when the Accounts service fails to provide a user list by logging a warning and aborting initialization of the user model.
  • Prevent undefined behavior when no users are returned by guarding access to the first user entry.
  • Allow session creation to succeed even when the requested username has no passwd entry by falling back to the current process user, while handling failure explicitly.
  • Avoid Treeland startup crashes due to a null global session by converting the assert into a runtime check with critical logging and early return.

1. session.cpp: fall back to getpwuid(getuid()) on getpwnam failure
2. usermodel.cpp: guard empty user list before .first() to avoid UB
3. usermodel.cpp: replace qFatal with qCWarning for D-Bus graceful fallback
4. treeland.cpp: replace Q_ASSERT(globalSession) with runtime null check

Log: treeland can now start normally even when no users exist

Influence:
1. Test treeland startup with no system users (empty /etc/passwd user list)
2. Test treeland startup when Accounts D-Bus service is unavailable
3. Verify treeland startup with normal user presence is unaffected
4. Test user switching and session management in edge-case scenarios

fix: 允许 treeland 在没有任何用户时正常启动

1. session.cpp: getpwnam 失败时回退到 getpwuid 确保全局会话可用
2. usermodel.cpp: 调用 .first() 前增加空列表守卫避免未定义行为
3. usermodel.cpp: qFatal 替换为 qCWarning 实现 D-Bus 优雅降级
4. treeland.cpp: Q_ASSERT 替换为运行时空指针检查

Log: treeland 现在可以在没有任何用户的情况下正常启动

Influence:
1. 测试在无系统用户时启动 treeland 不会崩溃
2. 测试 Accounts D-Bus 服务不可用时 treeland 启动正常
3. 验证正常用户场景下 treeland 启动不受影响
4. 测试边界场景下的用户切换与会话管理功能

Fixes: linuxdeepin#82
@Groveer
Groveer marked this pull request as draft July 15, 2026 08:25
@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Groveer

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

@sourcery-ai

sourcery-ai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Reviewer's Guide

Ensures Treeland and its greeter start gracefully when no system users or the expected "dde" user exist by adding runtime fallbacks and null/empty checks, and by downgrading fatal errors to logged warnings where appropriate.

Sequence diagram for Treeland startup and session fallback

sequenceDiagram
    participant Treeland
    participant Helper
    participant SessionManager
    participant passwd_db

    Treeland->>Helper: helper
    Helper->>SessionManager: globalSession()
    SessionManager->>passwd_db: getpwnam(username)
    alt passwd entry found
        passwd_db-->>SessionManager: passwd
        SessionManager-->>Helper: Session
    else passwd entry missing
        passwd_db-->>SessionManager: null
        SessionManager->>passwd_db: getpwuid(getuid())
        alt current user passwd found
            passwd_db-->>SessionManager: passwd
            SessionManager-->>Helper: Session
        else current user passwd missing
            passwd_db-->>SessionManager: null
            SessionManager-->>Helper: nullptr
        end
    end
    Helper-->>Treeland: globalSession
    alt globalSession is null
        Treeland->>Treeland: qCCritical(lcTlCore)
        Treeland->>Treeland: return
    else globalSession valid
        Treeland->>Treeland: proceed initialization
    end
Loading

Sequence diagram for UserModel initialization with empty or failing user list

sequenceDiagram
    participant UserModel
    participant AccountsManager as Manager

    UserModel->>Manager: userList()
    alt userList has error
        Manager-->>UserModel: error
        UserModel->>UserModel: qCWarning(lcTlGreeter)
        UserModel->>UserModel: return
    else userList ok
        Manager-->>UserModel: uids
        UserModel->>UserModel: populate d->users
        alt currentUserName is empty
            alt d->users is empty
                UserModel->>UserModel: qCWarning(lcTlGreeter)
            else d->users not empty
                UserModel->>UserModel: qCWarning(lcTlGreeter)
                UserModel->>UserModel: d->currentUserName = d->users.first()->userName()
            end
        else currentUserName set
            UserModel->>UserModel: keep currentUserName
        end
    end
Loading

File-Level Changes

Change Details Files
Make session creation resilient when the expected username passwd entry is missing by falling back to the current process user.
  • Include unistd.h to access getuid
  • Log a warning when getpwnam for the requested username fails and document the fallback behavior
  • Fallback to getpwuid(getuid()) when getpwnam fails
  • Log a critical error and return nullptr if getpwuid also fails before constructing the Session
src/session/session.cpp
Harden the greeter user model against Accounts service failures and an empty user list to avoid crashes and undefined behavior.
  • Replace qFatal on failed userList() retrieval with a categorized warning and early return
  • Guard access to d->users.first() with an isEmpty check before defaulting currentUserName
  • Adjust warning messages to reflect either no users found or fallback to first user
src/greeter/usermodel.cpp
Prevent Treeland from crashing on startup when globalSession is null by replacing an assertion with a runtime check and early exit, and update copyright years.
  • Update the copyright header years from 2023 to 2023-2026
  • Replace Q_ASSERT(globalSession) with an if check that logs a critical error and returns early when globalSession is null
src/core/treeland.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

@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 left some high level feedback:

  • In SessionManager::ensureSession, falling back from the requested username to getuid() may be surprising; consider logging the original username and/or propagating a distinct error or status so callers can distinguish between “requested user not found” and “fallback to current user.”
  • The early return in Treeland::Treeland when globalSession is null leaves a partially initialized object; consider moving the check to a factory or init method that can fail explicitly rather than returning from the constructor, or set an explicit "invalid" state that callers can query.
  • When UserModel returns early due to a failure in userList(), ensure all dependent code paths can handle an empty d->users and d->currentUserName gracefully; if needed, add a simple validity flag or getter to make this state explicit to consumers.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `SessionManager::ensureSession`, falling back from the requested `username` to `getuid()` may be surprising; consider logging the original username and/or propagating a distinct error or status so callers can distinguish between “requested user not found” and “fallback to current user.”
- The early `return` in `Treeland::Treeland` when `globalSession` is null leaves a partially initialized object; consider moving the check to a factory or init method that can fail explicitly rather than returning from the constructor, or set an explicit "invalid" state that callers can query.
- When `UserModel` returns early due to a failure in `userList()`, ensure all dependent code paths can handle an empty `d->users` and `d->currentUserName` gracefully; if needed, add a simple validity flag or getter to make this state explicit to consumers.

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-bot

deepin-bot Bot commented Jul 17, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 0.8.15
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1163

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.

2 participants