Ubuntu – GNOME: supend on laptop lid close no longer works since 19.10 upgrade

gdmgnomegnome-settings-daemonsuspendsystemd-logind

I'm quite positive that this used to work flawlessly in 19.04 (and past releases) but no longer does after a release-upgrade to 19.10 (kernel 5.3.0-24, ThinkPad X1 Carbon gen 5 in case this matters).

I have the corresponding switch set in GNOME-Tweaks and have also attempted to manually edit /etc/systemd/logind.conf as suggested here, namely uncomment and adjust the following lines, followed by a reboot:

$ grep -v '^#' /etc/systemd/logind.conf
[Login]
HandleLidSwitch=suspend
HandleLidSwitchExternalPower=suspend
HandleLidSwitchDocked=suspend
LidSwitchIgnoreInhibited=yes

(strictly speaking, only the first one ought to be required but, just in case, I also added lines 2 & 3, as well as #4 for good measure…

Looking at the output of systemctl status systemd-logind, I see the following:

Dec 17 17:56:50 x1c5 systemd-logind[8959]: Lid closed.
Dec 17 17:57:03 x1c5 systemd-logind[8959]: Lid opened.

So the lid events are correctly detected. To rule out any issue with the suspend process itself, I have also set my power button to suspend in Settings->Power->Suspend & Power Button, for testing purposes. Pressing the power button now results in this in the output of systemctl status systemd-logind (after a successful suspend-resume cycle):

Dec 17 18:13:58 x1c5 systemd-logind[8959]: Power key pressed.
Dec 17 18:14:28 x1c5 systemd-logind[8959]: Delay lock is active (UID 121/gdm, PID 9215/gsd-power) but inhibitor timeout is reached.
Dec 17 18:14:39 x1c5 systemd-logind[8959]: Operation 'sleep' finished.

Bottom line: lid events are detected correctly and suspend works flawlessly – but not on lid close…

Any idea how I can get the suspend on lid-close feature back to life? I can of course use the workaround with the power button but it's a little too easy to forget and result in laptop overheating in bag etc…

— edited to add —

Got a little further courtesy of this ticket, although the issue isn't the exactly as described. Here's a smoking gun:

$ systemd-inhibit --list --mode=block
WHO       UID  USER      PID  COMM           WHAT                                                     WHY                                                         MODE 
gdm       121  gdm       2231 gsd-power      handle-lid-switch                                        External monitor attached or configuration changed recently block
gdm       121  gdm       2252 gsd-media-keys handle-power-key:handle-suspend-key:handle-hibernate-key GNOME handling keypresses                                   block
user      1000 user      3017 gsd-media-keys handle-power-key:handle-suspend-key:handle-hibernate-key GNOME handling keypresses                                   block

This suggests that the lid close action is being blocked because "External monitor attached or configuration changed recently". I do connect my laptop to a monitor using a USB-C cable but as I write this, it's been undocked and running on batteries for nearly 3 hours (GNOME settings only shows my laptop display as available). However it looks like systemd or whichever component is responsible for this still incorrectly believes the external display is attached and – per the ticket – suspend isn't supported by GNOME in such scenarios…

Interestingly the gsd-power process (PID 2231) is owned by gdm rather than my UID. Killing it restores the suspend-on-lid-close functionality. Need to figure out why this process exists… When actually connected to external display, systemd-inhibit --list --mode=block reports a 2nd gsd-power process owned by the interactive user; which appears correct and sufficient.

Best Answer

Per investigations at the end of the question, the issue appears to be caused by GDM running a redundant gsd-power process. This can simply be killed as soon as you log in. Here's how I've done it:

  1. Create a kill script as follows:

    script=~/bin/kill_gdm_gsd-power.sh
    cat > $script << EOF
    #!/bin/sh
    sudo pkill -u gdm gsd-power
    EOF
    chmod 755 $script
    
  2. Your account will need to be allowed to run sudo pkill without a password prompt (make sure you're comfortable with this). Run sudo visudo -f /etc/sudoers.d/NOPASSWD and enter the following

    Cmnd_Alias PKILL = /usr/bin/pkill
    user ALL=(ALL) NOPASSWD: PKILL
    

    (replace user above with your own user id)

  3. Open the GNOME startup apps applet (gnome-session-properties) and add an entry with your script, so it runs as soon as you log on.

Ideally we'd find a way to prevent gsd-power from starting up altogether but I found this non-trivial... Please chip in if you find a better way.

A slightly cleaner solution might be to cook a custom handle-lid-switch script per this solution but the script would primarily have to be installed for the gdm user and this may also not be trivial...

There might be some side-effects to killing gdm's gsd-power process, eg: if you log out and leave the laptop to the GDM greeting screen but I think this isn't a scenario many of us will run into.

Related Question