Skip to content

Restarting ddm unconditionally stops treeland.service during normal daemon shutdown #98

@zccrs

Description

@zccrs

Summary

systemctl restart ddm is currently destructive to the Treeland display stack because ddm tears down treeland.service during normal daemon shutdown.

That means restarting the display manager is not just restarting the greeter backend; it also tears down the compositor that DDM is managing.

Current code path

In src/daemon/DaemonApp.cpp, SIGTERM and SIGINT are connected to QCoreApplication::quit().

During shutdown, Display objects are destroyed, and Display::~Display() calls stop().

Display::stop() then calls m_treeland->stop(), and TreelandDisplayServer::stop() does:

systemd.call("StopUnit", "treeland.service", "replace");

So a normal ddm service stop/restart ends up stopping the system treeland.service as part of DDM teardown.

Why this is a problem

In the Treeland integration path, DDM is not only serving a login prompt. It is also coordinating the compositor-backed greeter/session switching path.

Making ddm restart destructive has a few bad effects:

  • restart ddm is not a control-plane-only operation
  • crash recovery and package upgrade restarts become much riskier than they need to be
  • active Treeland-managed session state can be disrupted even though the user did not ask to stop the compositor

Reproduction / reasoning

This is directly visible from the current shutdown path:

  • ddm.service receives stop/restart
  • DaemonApp quits on SIGTERM
  • Display::~Display() runs
  • Display::stop() runs
  • TreelandDisplayServer::stop() calls StopUnit("treeland.service")

This does not depend on a special failure path. It is the normal stop path.

Proposed direction

DDM should distinguish between:

  1. intentionally shutting down the whole display/compositor stack
  2. restarting or crashing the DDM daemon itself

Possible fixes:

  • Do not unconditionally call StopUnit("treeland.service") from Display::~Display() / Display::stop() on daemon shutdown.
  • Keep treeland.service running across DDM restart and reconnect from the new DDM instance.
  • If a full teardown is still needed in some cases, gate it behind an explicit mode instead of the generic destructor path.

Related follow-up

There is a second resilience gap in the same area: DdeSeatdControl drops its event socket on error and does not attempt to reconnect, so an unexpected dde-seatd restart/crash can leave DDM alive but blind to future VT change events.

Files

  • src/daemon/DaemonApp.cpp
  • src/daemon/Display.cpp
  • src/daemon/TreelandDisplayServer.cpp

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions