Skip to content

Use the existing user D-Bus session bus instead of spawning dbus-launch - #212

Open
Fantu wants to merge 3 commits into
linuxmint:masterfrom
Fantu:dbus-session-address
Open

Use the existing user D-Bus session bus instead of spawning dbus-launch#212
Fantu wants to merge 3 commits into
linuxmint:masterfrom
Fantu:dbus-session-address

Conversation

@Fantu

@Fantu Fantu commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Fixes #210.

require_dbus_session() only looks at DBUS_SESSION_BUS_ADDRESS. When that variable is unset it re-execs the whole session under dbus-launch --exit-with-session, even when the user already has a session bus running on the well-known socket at $XDG_RUNTIME_DIR/bus — the default under systemd, and also the case on elogind setups with dbus configured for the user bus.

Two things go wrong:

  • a second bus is started, so activatable services and portals end up split across two buses;
  • on systems that ship no dbus-launch binary (a Debian install with only dbus-user-session, no dbus-x11) that fallback cannot work at all.

X11 logins usually escape this because the display manager wraps the session in a script that exports DBUS_SESSION_BUS_ADDRESS; the Wayland session does not go through those wrappers, so it depends on the display manager.

What the branch does

Commit
main.c: Use the existing user D-Bus session bus instead of spawning dbus-launch. Ask GDBus for the session bus address first and export it, so every child of the session ends up on the same bus. The dbus-launch fallback stays for setups without a user bus. This is what gnome-session does in leader-main.c.
build: Require GLib 2.50. The declared minimum, 2.37.3, has not matched the code for a long time (g_settings_schema_list_keys() needs 2.46, g_strv_contains() and the g_autoptr/g_autofree macros need 2.44, GSubprocess and GVariantDict need 2.40). 2.50 is the version where g_dbus_address_get_for_bus_sync() gained the fallback to $XDG_RUNTIME_DIR/bus that the first commit relies on.
main.c: Report the failure when dbus-launch cannot be executed. execvp() returns only when it failed, and then always returns -1, so if (!execvp (...)) was never true and the g_set_error() branch was dead code: instead of failing with "No session bus and could not exec dbus-launch", the function fell through to the return TRUE marked "Should not be reached" and the session carried on with no session bus at all, silently. Found while testing this branch.

Testing

Tested against 6.6.4 on Debian sid — require_dbus_session() is identical there and on master, so the change applies unmodified. Both a package build (sbuild, sid chroot) and a real desktop session (KVM VM, lightdm + Cinnamon, X11 and Wayland) were used.

Behaviour of require_dbus_session(), checked with strace -f -e trace=execve on cinnamon-session --version, which runs before option parsing:

Scenario Before After
User bus on $XDG_RUNTIME_DIR/bus, variable unset execs dbus-launch, which forks a second dbus-daemon --session no dbus-launch exec at all, address taken from the running user bus
No user bus, dbus-launch available falls back to dbus-launch unchanged
No user bus, no dbus-launch prints the version and continues without a bus, no error Unable to start session: No session bus and could not exec dbus-launch: No such file or directory, session aborts

Real session, lightdm autologin into Cinnamon:

  • X11 and Wayland logins: session comes up on the single user bus, all org.cinnamon.* services plus the gtk/xapp portals on it, systemctl --user show-environment consistent, no second dbus-daemon --session.
  • Logout and log back in: clean, no leftover session processes, the same user bus is reused by the new session.
  • Sessions were also started with the variable explicitly removed (Exec=env -u DBUS_SESSION_BUS_ADDRESS cinnamon-session-cinnamon --wayland), which is what a display manager that does not export it looks like. With the branch, the session starts and its children inherit DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus. Without it, and with dbus-x11 installed, the session dies at startup — Unable to start session: Lost name on bus: org.gnome.SessionManager — and lightdm falls back to the greeter.

Two notes for whoever reviews this, since they explain why the bug is rarely seen:

  • on a current systemd system it is pam_systemd itself that exports DBUS_SESSION_BUS_ADDRESS (checked on systemd 261: the string is in pam_systemd.so, and without PAM the variable is absent). So every PAM session — X11, Wayland, su -, ssh — already has it, and the dbus-launch path is unreachable there. The change matters for setups that do not get it from PAM, elogind among them.
  • with the variable unset and no dbus-launch installed, the session still comes up today, because every GIO client falls back to $XDG_RUNTIME_DIR/bus on its own; the children just never see the variable. The visible breakage needs dbus-launch to be present.

Related Debian bug: https://bugs.debian.org/835846

Fantu added 3 commits August 7, 2026 16:29
…bus-launch.

require_dbus_session() only looked at DBUS_SESSION_BUS_ADDRESS, so with
the variable unset it re-exec'd the session under `dbus-launch
--exit-with-session` even when the user already had a session bus
running on the well-known socket at $XDG_RUNTIME_DIR/bus (the default on
systemd, and on elogind setups with dbus configured for the user bus).
That starts a second bus, splitting activatable services and portals
across the two, and on systems that ship no dbus-launch binary (Debian
with only dbus-user-session installed) the session does not start at
all.

X11 logins usually escape this because the display manager wraps the
session in a script that exports DBUS_SESSION_BUS_ADDRESS, but the
Wayland session does not go through those wrappers, so it depends on the
display manager.

Ask GDBus for the session bus address first: it looks for the socket at
$XDG_RUNTIME_DIR/bus, and we export the address so every child of the
session ends up on the same bus. The dbus-launch fallback stays for
setups without a user bus, so nothing changes there. This is what
gnome-session does in leader-main.c.

Closes: linuxmint#210

Assisted-by: Claude Code:claude-opus-5
The declared minimum, 2.37.3, has not matched the code for a long time:
g_settings_schema_list_keys() in csm-autostart-app.c needs 2.46,
g_strv_contains() and the g_autoptr/g_autofree macros need 2.44, and the
GSubprocess and GVariantDict API need 2.40.

Ask for 2.50 rather than 2.46: that is the version where
g_dbus_address_get_for_bus_sync() started falling back to the well-known
socket at $XDG_RUNTIME_DIR/bus, which is what lets the previous commit
pick up the user session bus instead of spawning dbus-launch.

Assisted-by: Claude Code:claude-opus-5
execvp() returns only when it failed, and then it always returns -1, so
`if (!execvp (...))` was never true: the g_set_error() branch was dead
code. Instead of failing with "No session bus and could not exec
dbus-launch", require_dbus_session() fell through to the `return TRUE`
marked "Should not be reached" and the session kept going with no
session bus at all, silently, until something else broke further down.

Call execvp() and treat its return as the failure it is.

This is easier to hit than it looks on systems that ship no dbus-launch
binary, and the previous commit does not change that: it only makes the
fallback rarer, not the failure mode better.

Assisted-by: Claude Code:claude-opus-5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Use the existing user D-Bus session ($XDG_RUNTIME_DIR/bus) instead of spawning dbus-launch

1 participant