Skip to content

Start the daemon on Ubuntu GNOME login - #277

Merged
Anuraj-dev merged 2 commits into
mainfrom
fix/ubuntu-gnome-login-start
Sep 28, 2026
Merged

Anuraj-dev merged 2 commits into
mainfrom
fix/ubuntu-gnome-login-start

Conversation

@Anuraj-dev

Copy link
Copy Markdown
Owner

Problem

On Ubuntu 26.04 / GNOME 50 (voisu 0.63.0 deb), voisu.service was dead after every login:

Condition: start condition unmet
  ConditionEnvironment=|WAYLAND_DISPLAY was not met
  ConditionEnvironment=|DISPLAY was not met
05:02:59 voisu.service - skipped, no trigger condition checks were met.
05:03:00 Reached target graphical-session.target

systemd checked the unit's display conditions before gnome-shell had imported WAYLAND_DISPLAY/DISPLAY into the user manager. It never retries a skipped condition, so the unit stayed dead until a manual systemctl --user start.

Result

  • The daemon unit no longer has ConditionEnvironment. Under --systemd the daemon waits for the display itself, with a real 20 s deadline that includes query time.
    • If WAYLAND_DISPLAY/DISPLAY appears in the user manager environment, it exits 75 and Restart=on-failure respawns it with that environment.
    • If neither appears, it exits 78. RestartPreventExitStatus=78 then leaves a failed unit instead of a restart loop, and voisu doctor points at the journal.
  • Both units, and the unit generated by voisu service install, order After=graphical-session.target. This does not cycle with WantedBy= it. The earlier recorded cycle came from After=xdg-desktop-portal.service, and that is still forbidden.
  • The overlay unit keeps ConditionEnvironment=WAYLAND_DISPLAY. On GNOME the Overlay is the Shell extension, so that unit is unused there.
  • The README gains an Ubuntu GNOME troubleshooting section:
    • SKIP rows for Hyprland-only Paste checks and the Focus guard WARN are expected.
    • The extension is the Overlay.
    • Delivery pastes with a Ctrl+V keystroke, so a terminal needs a manual paste from the clipboard.
    • How to reset the RemoteDesktop restore token.

Not in this PR: the "autopaste lands nothing" report. On GNOME, Direct Delivery submits Ctrl+V through libei unless the seat offers text input, so a terminal that pastes with Ctrl+Shift+V gets nothing. That is the leading hypothesis, but it is unconfirmed without a clean retest on the reporter's machine, so this PR documents it rather than changing Delivery.

Verification

  • cargo fmt --all -- --check, cargo clippy --workspace --all-targets --locked -- -D warnings, cargo test --workspace --locked: all exit 0.
  • New tests:
    • system::display_wait unit tests use a fake clock and cover:
      • display already present
      • display arrives while waiting
      • unreadable manager
      • slow queries counted against the deadline
      • final sleep capped to the remaining time
      • exit codes 75 and 78
    • tests/daemon_display_wait.rs drives the real binary through a fake systemctl.
  • Real host (Arch, systemd 261):
    • A transient unit that exits 75 respawned and picked up a variable set with systemctl --user set-environment in between.
    • The built voisu-daemon --systemd ran as a transient unit with the packaged sandbox properties and without display variables. It reached the user manager, logged the arrival line, and exited 75.
  • systemd-analyze --user verify passes for both units.
  • Independent review: gpt-6-sol medium, two rounds. Round 1 found that ordering alone did not prove the fix, which led to the daemon-side wait. Round 2's single MEDIUM, that query time was not counted toward the deadline, is fixed here without a third review, per the review-cycle cap.
  • Not verified: a real Ubuntu 26.04 GNOME cold login.

On Ubuntu 26.04 / GNOME 50, systemd evaluated voisu.service's
ConditionEnvironment=|WAYLAND_DISPLAY / |DISPLAY before gnome-shell had
imported them into the user manager, skipped the unit, and never retried,
so the daemon was dead after every login.

The daemon unit no longer carries a start condition. Under --systemd the
daemon waits up to 20 s for a display variable in the user manager
environment: when one arrives it exits 75 so Restart=on-failure respawns
it with the manager's current environment; if none arrives it exits 78,
which RestartPreventExitStatus turns into a failed unit instead of a
restart loop. Both units also order after graphical-session.target.

The README gains an Ubuntu GNOME troubleshooting section covering the
expected doctor SKIP/WARN rows, the Shell-extension Overlay, clipboard
paste fallback, and resetting the RemoteDesktop restore token.
The --systemd display wait made this test depend on the host having
WAYLAND_DISPLAY; on CI it waited 20 s and exited 78.
@Anuraj-dev
Anuraj-dev merged commit 71d13f6 into main Sep 28, 2026
6 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.

1 participant