1

Xorg integrates with systemd-logind, allowing it to effectively open the devices it needs without being run as the super-privileged root user. When the systemd-logind session ends, systemd-logind revokes Xorg's access to the devices (revoking the file descriptors[1]).

But does ending the session actually cause Xorg to quit?

This question was written as of Fedora version 26, xorg-x11-server-Xorg-1.19.3-4.fc26.x86_64.


[1] Or technically, I think logind revokes the descriptions created when it opened the devices. File descriptors are per-process; logind can't directly affect the descriptors in the Xorg process.

2

No. The code does not listen for it, and it can blithely continue running without access to any devices (and no expectation of re-gaining access). I believe this is an oversight in Xorg's integration with systemd-logind.

Currently Xorg requires to be run in the "scope" unit associated with the session. Although it could be extended to accept the XDG_SESSION_ID environment variable instead. That's what originally prompted my question.

If the session ends by the session leader (first process) exiting, the scope will only be stopped if the upstream default KillUserProcesses=yes has been left in logind.conf. Otherwise, the session is "abandoned", allowing processes like GNU Screen or tmux to continue running. Most distributions disable KillUserProcesses; it's a very questionable default.

loginctl terminate-session will always stop the scope unit. Although, stopping the scope unit initially sends SIGHUP, apparently because "bash and friends" tend to ignore SIGTERM. For some reason. Xorg, like many daemons, treats SIGHUP specially. Xorg treats SIGHUP as a signal to reset the server, instead of quitting. I think this means systemd would then send SIGKILL, after a timeout had elapsed and Xorg had still not exited. Xorg would be forcibly killed without having properly cleaned up.

Steps to reproduce Xorg not quitting:

  1. Run nohup /usr/libexec/Xorg :5 vt5 -keeptty -novtswitch as a non-root user. (vt5 assuming you run this from text console 5, AKA ctrl+alt+f5).
  2. Switch to a different text console. Log in. Use ps -ax | grep bash to find the PID of the bash shell running on tty5. Run kill -SIGHUP <PID>
  3. The bash process exits, logging out your session. If you switch back to VT 5, you will see the console login prompt. But the Xorg process is actually still running!

    In the log file for this instance of Xorg, you will see that it tried to release and re-open all the devices it still thinks belong to it. That's what happens when Xorg is reset. None of the devices are available to it now the session is over, so all the attempts to open devices fail.

    Xorg resets because it is sent SIGHUP (despite nohup :-). I noticed this because I'd attached gdb to it. SIGHUP is received because Xorg re-opened /dev/tty5 itself, acquiring it as the "controlling terminal". You can see the controlling terminal in ps -ax | grep Xorg. When you killed bash to force a logout, the system generated a hangup (HUP) on the TTY. Unless you have KillUserProcesses set, nothing stronger than SIGHUP will be sent to Xorg.

Without novtswitch, the reset also attempts to switch VTs. But non-root X can never change the active VT. Since step 3 is run from a different VT, this VT switch attempt will fail. The failure to switch VTs causes Xorg to exit.

The nohup in these steps is required otherwise Xorg will be terminated. This has to do with shell job management. Proof: Xorg also continues running if you don't use nohup, but instead disable job management using the command set +m.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.