In my previous post I mentioned a problem that I had still not been able to fix in a single-seat, multi-user installation of Lubuntu 18.04: Xfce Power Manager in each user’s account can cause the installation to suspend to RAM if a user has not logged out of his/her session and another user is using a different session. Each user account in Lubuntu 18.04 has its own XfcePower Manager settings, stored in the file ~/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-power-manager.xml
. If the property /xfce4-power-manager/inactivity-on-ac
has a value of 15 (minutes) or higher, that session can cause the machine to suspend to RAM even if the session is not active while someone else’s session is active. The example below illustrates the effect.
Consider five users mick
, christine
, john
, stevie
and lindsey
with the following settings for the number of minutes of inactivity that will trigger suspension to RAM:
mick@aspirexc600:~$ xfconf-query -c xfce4-power-manager -p /xfce4-power-manager/inactivity-on-ac
30
christine@aspirexc600:~$ xfconf-query -c xfce4-power-manager -p /xfce4-power-manager/inactivity-on-ac
25
john@aspirexc600:~$ xfconf-query -c xfce4-power-manager -p /xfce4-power-manager/inactivity-on-ac
45
stevie@aspirexc600:~$ xfconf-query -c xfce4-power-manager -p /xfce4-power-manager/inactivity-on-ac
15
lindsey@aspirexc600:~$ xfconf-query -c xfce4-power-manager -p /xfce4-power-manager/inactivity-on-ac
30
Now, suppose that john
boots the machine, logs in to his account to check his e-mail, leaves the e-mail client open and goes off to grab lunch without logging out. Then stevie
comes along and clicks on ‘Logout’ > ‘Switch User’ to display the LightDM greeter screen (or the greeter screen is already displayed because john
‘s session has already been locked), logs in to her account and begins to use, say, LibreOffice Writer. Even though stevie
is busy typing, the machine will suspend to RAM after 45 minutes of inactivity by john
. This can be very annoying.
In addition to the individual users’ Xfce Power Manager configuration files in Lubuntu 18.04, I found the following Xfce Power Manager configuration files which appear to be system-wide:
/etc/xdg/xdg-Lubuntu/xfce4/xfconf/xfce-perchannel-xml/xfce4-power-manager.xml
/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-power-manager.xml
First attempt at fixing the problem
I asked all the users to configure their accounts to never cause the machine to suspend, by using the Xfce Power Manager settings GUI in their session and selecting ‘Never’. I noticed this caused each user’s /xfce4-power-manager/inactivity-on-ac
property to become ‘14
‘:
user $ xfconf-query -c xfce4-power-manager -p /xfce4-power-manager/inactivity-on-ac
14
Note that users must not edit their file ~/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-power-manager.xml
; if they do, the settings shown in the Xfce Power Manager settings GUI will not be updated. Users must either use the Xfce Power Manager settings GUI or xfconf-query
commands as explained on the askubuntu Web page ‘Change xfce4-power-manager option from terminal‘.
Then I edited the file /etc/xdg/xdg-Lubuntu/xfce4/xfconf/xfce-perchannel-xml/xfce4-power-manager.xml
to make its contents the same as the previous contents of the individual users’ settings when Suspend to RAM was enabled individually):
<?xml version="1.0" encoding="UTF-8"?>
<channel name="xfce4-power-manager" version="1.0">
<property name="xfce4-power-manager" type="empty">
<property name="power-button-action" type="uint" value="3"/>
<property name="show-tray-icon" type="bool" value="true"/>
<property name="brightness-switch-restore-on-exit" type="int" value="1"/>
<property name="brightness-switch" type="int" value="0"/>
<property name="presentation-mode" type="bool" value="false"/>
<property name="inactivity-on-ac" type="uint" value="30"/>
<property name="blank-on-ac" type="int" value="10"/>
<property name="dpms-on-ac-sleep" type="uint" value="0"/>
<property name="dpms-on-ac-off" type="uint" value="0"/>
<property name="brightness-on-ac" type="uint" value="9"/>
<property name="lock-screen-suspend-hibernate" type="bool" value="true"/>
<property name="logind-handle-lid-switch" type="bool" value="false"/>
<property name="dpms-enabled" type="bool" value="false"/>
<property name="general-notification" type="bool" value="true"/>
<property name="sleep-button-action" type="uint" value="0"/>
<property name="hibernate-button-action" type="uint" value="0"/>
</property>
</channel>
After rebooting, leaving one or more users logged in without any activity did not cause the installation to suspend to RAM after 30 minutes of no activity in any session.
So I then edited the file /etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-power-manager.xml
to make its contents the same as the above. After rebooting, leaving one or more users logged in without any activity did not cause the installation to suspend to RAM after 30 minutes of no activity in any session.
I therefore assume that the above two files are ignored by Xfce Power Manager during normal operation.
Second attempt at fixing the problem
I used the procedure given in the Xfce4-power-manager FAQs to check if Xfce Power Manager in Lubuntu 18.04 uses systemd-logind to suspend the installation, and indeed it does:
TRACE[xfpm-polkit.c:366] xfpm_polkit_check_auth_intern(): Action=org.freedesktop.login1.suspend is authorized=TRUE
Therefore I edited /etc/systemd/logind.conf
to add IdleAction=suspend
and IdleActionSec=30min
, and rebooted. However, this had no discernable effect either. Leaving one or more users logged in without any activity did not cause the installation to suspend to RAM after 30 minutes of no activity in any session.
Third attempt (successful) at fixing the problem
So, what to do?! In my previous post I explained how I had fixed the problem of not being able to suspend to RAM automatically from the LightDM greeter screen. I decided to keep the scripts from that post and add a new script sessions_sleep.sh
to the root crontab. The contents of all the files and the crontab are shown below.
user $ cd /etc/lightdm/lightdm.conf.d/
user $ cat 10_lubuntu.conf
[Seat:*]
greeter-setup-script=/etc/lightdm/lightdm.conf.d/lightdm_sleep.sh
session-setup-script=/etc/lightdm/lightdm.conf.d/lightdm_kill_sleep.sh
session-cleanup-script=/etc/lightdm/lightdm.conf.d/unmount_FREECOM_HDD.sh
user $ ls
05_lubuntu.conf lightdm_kill_sleep.sh sessions_sleep.sh
10_lubuntu.conf lightdm_sleep.sh unmount_FREECOM_HDD.sh
user $ cat lightdm_sleep.sh
#!/bin/bash
# This forms part of the scheme to provide automatic suspension while the greeter screen is displayed
file="/tmp/unique_identifier"
(while true; do sleep 30m; systemctl suspend; done) &
echo $! > $file
user $ cat lightdm_kill_sleep.sh
#!/bin/bash
# This forms part of the scheme to provide automatic suspension while the greeter screen is displayed
file="/tmp/unique_identifier"
if [ -f "$file" ]; then
kill `cat $file`
rm $file
fi
user $ tail -n 11 unmount_FREECOM_HDD.sh
#----------------------------------------------------------------------------------------------------
#
# This forms part of the scheme to provide automatic suspension while the greeter screen is displayed
file="/tmp/unique_identifier"
if [ -f "$file" ]; then
kill `cat $file`
rm $file
fi
#
#----------------------------------------------------------------------------------------------------
exit 0
If the machine did not already have a permanently-connected external USB HDD (LABEL=”FREECOM HDD”) then it would have sufficed to specify a script named, for example, lightdm_kill_sleep2.sh
instead of unmount_FREECOM_HDD.sh
:
user $ cat 10_lubuntu.conf
[Seat:*]
greeter-setup-script=/etc/lightdm/lightdm.conf.d/lightdm_sleep.sh
session-setup-script=/etc/lightdm/lightdm.conf.d/lightdm_kill_sleep.sh
session-cleanup-script=/etc/lightdm/lightdm.conf.d/lightdm_kill_sleep2.sh
user $ cat lightdm_kill_sleep2.sh
#!/bin/bash
# This forms part of the scheme to provide automatic suspension while the greeter screen is displayed
file="/tmp/unique_identifier"
if [ -f "$file" ]; then
kill `cat $file`
rm $file
fi
user $ sudo nano sessions_sleep.sh
user $ sudo chmod +x sessions_sleep.sh
user $ cat sessions_sleep.sh
#!/bin/bash
date +%s > /tmp/datetime_suspended # Initialise variable
while true
do
# Only monitor idle time and suspend after specified inactivity if lightdm_sleep.sh is not taking care of those
if [[ `ps -ef | grep bash | grep lightdm_sleep.sh | wc -l` -eq 0 ]]; then
#-------------------------------STAGE 1: FIND OUT WHO IS THE ACTIVE USER--------------------------------------
#
while IFS=: read -r f1 f2 f3 f4 f5 f6 f7
# $f1 is username
# $f2 is password ('x')
# $f3 is UID
# $f4 is GID
# $f5 is UID info
# $f6 is home directory
# $f7 is command/shell
do
if [[ $f6 == *"/home/"* ]] && [[ $f7 == "/bin/bash" ]]; then
if `loginctl list-users | grep -ve '^$\|USER\|listed' | awk -F' ' '{print $2}' | grep -q $f1`; then
state=`loginctl show-user $f3 | grep State | awk -F'=' '{print $2}'`
if [[ $state != "active" ]]; then
inactive_user=$f1
elif [[ $state == "active" ]]; then
active_user=$f1
fi
fi
fi
done < /etc/passwd
#
#-------------------------------STAGE 2: ASCERTAIN USER SESSIONS---------------------------------------------
#
# Find idle time for each X Windows session and suspend to RAM if the active user has been idle for >=30min.
#
who -u | grep -v "\." > /tmp/logged-in_users
#
while read a b c d e f g
# $a is username
# $b is the tty (tty1 to tty12)
# $c is the date (yyyy-mm-dd)
# $d is the time (hh:mm)
# $e is the idle time (hh:mm) which does not reflect reality in this installation, for some reason
# $f is the PID
# $g is the display e.g. "(:1)"
# Example: "john tty7 2019-08-31 17:08 00:01 1624 (:0)"
do
if [[ $(echo $b | sed 's/[^0-9]*//g') -gt 6 ]]; then
display=$(echo $g | sed 's/[^0-9]*//g')
idle_millisecs=$(env DISPLAY=:$display sudo -u $a xprintidle)
let idle_minutes=$idle_millisecs/60000
if [[ $idle_minutes -ge 30 ]] && [[ $a == "$active_user" ]]; then
datetime_now=$(date +%s)
diffsecs=$(expr $datetime_now - $(cat /tmp/datetime_suspended))
# Prevent suspending immediately after resuming
if [ $diffsecs -gt 180 ]; then
date +%s > /tmp/datetime_suspended
systemctl suspend
fi
fi
fi
done < /tmp/logged-in_users
rm /tmp/logged-in_users
#
#------------------------------------------------------------------------------------------------------------
sleep 10 # Frequency to repeat check
fi
done
I installed the utility xprintidle via the Linux distribution’s package manager. As the name of the utility suggests, it returns the time (in milliseconds) that an X Windows session has been idle. Nice utility, by the way.
user $ sudo crontab -e
user $ sudo crontab -l | grep -v ^#
@reboot sudo /etc/lightdm/lightdm.conf.d/sessions_sleep.sh
Note that, despite its name, ‘@reboot
‘ in the cron job will run the script after a cold boot as well as after a warm boot (reboot). Also note that the use of ‘sudo
‘ in the root cron job is not an error; it makes the root cron job use the root user’s environment variables.
Remember that the property /xfce4-power-manager/inactivity-on-ac
has to be configured to have a value of 14 (which corresponds to ‘Never’ in the Xfce Power Manager settings GUI) for every user. This should be done by each user using the Xfce Power Manager settings GUI in their own session.
Basically, the scheme works as follows: At boot, Lubuntu 18.04 launches the looping Bash script sessions_sleep.sh
, which remains running but does nothing because no X Windows users are logged in. When LightDM runs the greeter-setup-script
(lightdm_sleep.sh
) and displays the greeter screen, sessions_sleep.sh
still does nothing while lightdm_sleep.sh
is running and taking care of managing suspension. When an X Windows user logs in and LightDM’s session-setup-script
(lightdm_kill_sleep.sh
) kills the running script lightdm_sleep.sh
, the script sessions_sleep.sh
then takes over monitoring users’ activity in X Windows and triggers suspension if the active user has not used his/her session for 30 minutes. If an X Windows user logs out, LightDM’s session-cleanup-script
(unmount_FREECOM_HDD.sh
) also kills lightdm_sleep.sh
if it is running. When LightDM again runs its greeter-setup-script
(lightdm_sleep.sh
) and displays the greeter screen, that again inhibits sessions_sleep.sh
from taking any action if no X Windows user is logged in. This all sounds convoluted, but it seems to work fine so far.
Because Xfce Power Manager is no longer used to monitor idle time and trigger suspension, ‘Presentation mode’ in Xfce Power Manager can no longer prevent the system from suspending after 30 minutes of inactivity while someone is watching a long video or playing music, for example. However this is not a problem; to temporarily inhibit suspension the user can use the method given in my earlier post ‘How to move a mouse pointer automatically in Linux to simulate user activity‘.
The Lubuntu 18.04 architecture
I suspect most Lubuntu 18.04 installations are on laptops or desktop machines with a single user, i.e. single-seat, single-user installations. In such a case, unless the user has created multiple user accounts that he/she logs into concurrently (by using ‘Switch User’, for example), the machine will never suspend unexpectedly while the user is logged in and using the session. I think the way LightDM, light-locker, systemd-logind and Xfce Power Manager have been bundled in Lubuntu 18.04 to manage suspending to RAM is a dog’s breakfast. The design apparently does not take into consideration that different people could be logged in concurrently in a single-seat installation. Try forcing people to log off so that only one person is ever logged in — it won’t happen! To be interrupted by Suspend to RAM triggered by Xfce Power Manager due to inactivity in a different session is illogical; the system should not suspend when someone is actively using the system. Therefore, in my opinion, management of suspension (and hibernation) ought to be configured and managed system-wide, not on a per-user basis, and a design should not require users to hack the installation to the extent I have described above. I was ‘scratching an itch’, but users should not have to jump through hoops to get an installation to function in a sensible manner. For all I know there may be a simpler way of achieving the functionality in Lubuntu 18.04 that I have described in this post and my previous post, but, if there is, it is not obvious. LightDM, light-locker, systemd and Xfce Power Manager are developed by different people, and functionality such as suspension and hibernation does not seem to have been considered using ‘helicopter vision’. Designing disparate applications developed separately to work together holistically is not a trivial task.
Anyway, hopefully I have fixed the problem and also ‘scratched my itch’. No more unexpected suspensions while I am using the family desktop machine!