Lubuntu 16.04 on ARM: Turning off the “Suspend” etc. options
In short
On an embedded ARM-based Lubuntu 16.04, I had LXDE’s logoff dialog window offering suspend as an option, and when that was chosen, the system got itself into some nasty state with network and keyboard off. The serial console was still active, and yet, I was better off without it.
It turned out that the kernel was misconfigured to announce that it supported suspend to RAM:
# cat /sys/power/state freeze mem
So no wonder that option was presented to the user on GUI. The solution: Turn off the CONFIG_SUSPEND kernel compilation flag. Recompile, deploy, and that’s it:
# cat /sys/power/state #
And the faulty options were gone.
The rest of this post contains things I jotted down as I wasted time trying to find out what the problem was.
Irrelevant notes
- There’s a systemd-inhibit utility for preventing suspends and sleeps while a certain program is running. Essentially, it issues an “Inhibit” command with what / who, why /mode info on DBus for”org.freedesktop.login1″.
- polkit’s manual (“man polkit” lacks some info) directs to a list of directories with rules.d files written in JavaScript (!!!). The action/ directories are policy files, in XML, which describe who might be allowed what operation, and what to write (in several languages) in the dialog box asking for authentication (typically a password).
- Obtaining the sources for the study below
# apt-get source lxsession-logout # apt-get source systemd
A journey in the sources (more wasted time)
I tried to follow how lxsession-logout, which is LXDE’s program that displays the logout dialog box, decides which low-power modes to offer. And what actually happens when suspend is requested.
- lxsession-logout.c learns if the system can suspend (and hence the button shall be presented) by calling dbus_systemd_CanSuspend().
- which is implemented in lxsession-logout-dbus-interface.c, and calls systemd_query() with “CanSuspend” as its parameter
- which (implemented in the same file) in turn opens a session with “org.freedesktop.login1″ over DBus and issues a query
- Judging by the “BusName=org.freedesktop.login1″ directive in /lib/systemd/system/systemd-logind.service, systemd-logind.service, (running systemd-login) is answering this query.
- Looking in systemd’s login-dbus.c, “CanSuspend” calls the method method_can_suspend(), which in turn calls method_can_shutdown_or_sleep() with “org.freedesktop.login1.suspend” as the key argument, which calls bus_test_polkit() for an answer on that.
- Implemented in systemd/shared/bus-util.c, bus_test_polkit() makes a DBus query on “org.freedesktop.PolicyKit1″
- There are also references to upowerd in lxsession-logout.c, but since stopping this service changes nothing, I focused on logind.
- Judging by the “BusName=org.freedesktop.PolicyKit1″ directive in /lib/systemd/system/polkitd.service, polkitd.service (running /usr/lib/policykit-1/polkitd) answer this.
- Back to login-dbus.c, a “Suspend” request causes a call to method_suspend(), which calls method_do_shutdown_or_sleep(), which calls bus_manager_shutdown_or_sleep_now_or_later(), which calls execute_shutdown_or_sleep(). The “unitname” parameter traverses these calls with the value SPECIAL_SUSPEND_TARGET. There are several checks on the way that may cancel the request, but this is the chain to fulfilling it.
- execute_shutdown_or_sleep() issues a DBus request on “org.freedesktop.systemd1″ (I have a wild guess which process is on the other side).
- Apparently (without following the execution chain), systemd/src/sleep.c is responsible for putting the system in suspend mode and such. Among others, it writes to /sys/power/state. This is where it hit me that maybe the kernel’s configuration was the problem.