Bug 485623 - Powerdevil does not respect lid-switch inhibitor created with systemd-inhibit
Summary: Powerdevil does not respect lid-switch inhibitor created with systemd-inhibit
Status: CONFIRMED
Alias: None
Product: Powerdevil
Classification: Plasma
Component: general (show other bugs)
Version: 6.0.4
Platform: Neon Linux
: NOR normal
Target Milestone: ---
Assignee: Plasma Bugs List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-04-16 07:20 UTC by Oded Arbel
Modified: 2024-07-14 11:08 UTC (History)
5 users (show)

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments
Mockup for PowerDevil lid-switch handle by systemd (57.71 KB, image/png)
2024-04-18 08:00 UTC, Oded Arbel
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Oded Arbel 2024-04-16 07:20:36 UTC
SUMMARY
PowerDevil does not respect a user's request to prevent a laptop from going to sleep due to a lid switch action, using the `systemd-inhibit` command with the `--what=handle-lid-switch` option

This issue was originally reported as a Bug #457859 comment #2 and was moved to a new ticket at the request of developers.

STEPS TO REPRODUCE
1. Under _Energy Saving_ make sure the "When laptop lid closed" [sic] option for the current power state is set to "sleep".
2. Open a terminal and run `systemd-inhibit --what=handle-lid-switch --who=test --why=coz sleep infinity`
3. Close the laptop lid

OBSERVED RESULT
The laptop goes to sleep

EXPECTED RESULT
The laptop will not go to sleep

SOFTWARE/OS VERSIONS
Operating System: KDE neon Testing Edition
KDE Plasma Version: 6.0.4
KDE Frameworks Version: 6.2.0
Qt Version: 6.7.0
Kernel Version: 6.5.0-27-generic (64-bit)
Graphics Platform: Wayland
Processors: 20 × 12th Gen Intel® Core™ i7-12700H
Memory: 31.0 GiB of RAM
Graphics Processor: Mesa Intel® Graphics

ADDITIONAL INFORMATION
The default systemd behavior can be achieved by stopping PowerDevil (for example using `systemctl --user stop plasma-powerdevil.service`), after which closing the lid without inhibition causes the laptop to sleep while with the above inhibition command the laptop will not sleep on lid close.

When using `sudo` to run `systemd-inhibit`, PowerDevil will still attempt to put the laptop to sleep but it will first request authorization using a policykit dialog, and as the laptop lid is closed this authorization request will go unanswered and the laptop will not sleep, but its not really a good workaround due to requiring authorization to start and having an unexpected authorization dialog when opening the lid.

Natalie Clarius in Bug #457859 comment #13 has opined that the behavior reported in this ticket is probably the desired behavior in order to prevent users from making mistakes - to which I will answer that having APIs to let users do things is all about letting users make their own mistakes, see `rm -rf /` - it is a legit operation a user is allowed to issue.

Furthermore, I will contend the `systemd-inhibit --what=handle-lid-switch` is a real API with good use cases that is implemented and supported by various systems and environments and PowerDevil should not disable it.
Comment 1 Jakob Petsovits 2024-04-16 15:03:35 UTC
I'll mark this as confirmed. Natalie's opinion in Bug 457859 comment #13 regarded the "sleep" and "idle" inhibitors, which thankfully you've left out of this bug report so the comment doesn't apply here.

In a series of comments from Bug 457859 comment #5 to Bug 457859 comment #10, I fumbled my way toward a possible approach for fixing this. The current interfaces provided by systemd make it difficult to handle this correctly without polling, so I submitted https://github.com/systemd/systemd/issues/32196 to ask for interface improvements.

With polling, it would still be possible right now to implement "handle-lid-switch" inhibitors somewhat correctly. Summarizing my comments from the other bug, we would want to do something like this:

* Add an extra enum value for lid-switch inhibition to PolicyAgent::RequiredPolicy.

* In PolicyAgent::checkLogindInhibitions(), check to see if any "handle-lid-switch" inhibitors other than PowerDevil's own inhibitor are active at the time of lid closure. Set the policy if this is the case.

* Make PolicyAgent aware of the current lid switch state. Probably by adding a method PolicyAgent::setLidClosed(bool) to be called from HandleButtonEvents::onLidClosedChanged().

* When the lid is closed, manually call PolicyAgent::checkLogindInhibitions() to get the latest state of non-PowerDevil "handle-lid-switch" inhibitors, because systemd won't notify us of changes unless we can get the aforementioned interface improvements.

* In HandleButtonEvents::onLidClosedChanged(), after policies are updated, replace any configured action with a "DPMS off" in case we have a "handle-lid-switch" inhibitor present. Ensure we always either suspend or turn off the screen when the lid is closed, and always turn the screen back when the lid is opened again.

* In the absence of observable inhibitor change signals from systemd, if an inhibitor was present on lid closure, add a polling timer to periodically call PolicyAgent::checkLogindInhibitions() as long as the lid is still closed. Stop polling when the lid gets opened again.

* Execute the suspend action if the lid-switch inhibitor policy disappears while the lid is still closed.

This approximate approach should make "handle-lid-switch" inhibitors work as expected.
Comment 2 Oded Arbel 2024-04-18 07:59:02 UTC
(In reply to Jakob Petsovits from comment #1)
> * In the absence of observable inhibitor change signals from systemd, if an
> inhibitor was present on lid closure, add a polling timer to periodically
> call PolicyAgent::checkLogindInhibitions() as long as the lid is still
> closed. Stop polling when the lid gets opened again.
> 
> * Execute the suspend action if the lid-switch inhibitor policy disappears
> while the lid is still closed.

This is an important behavior - thanks for noting that. I've also failed to identify a way to implement this behavior without polling - and "polling sometimes" is even worse than "polling all the time". If that is the case, and as long as the systemd-logind RFE has not been rejected - maybe waiting for systemd-logind support is the right choice.

In the mean time - maybe it is possible to implement a PowerDevil setting of "don't inhibit lid-switch and let systemd-logind handle lid switch"?
Comment 3 Oded Arbel 2024-04-18 08:00:31 UTC
Created attachment 168638 [details]
Mockup for PowerDevil lid-switch handle by systemd

Maybe adding an "According to system configuration" option to the lid switch behavior selection. When switching to a policy where this is selected, PowerDevil will stop inhibiting lid-switch.
Comment 4 Eric 2024-07-12 19:37:19 UTC
This is still an issue in Plasma 6.1.2. Is there a fix or workaround out there?
Comment 5 Eric 2024-07-12 21:09:18 UTC
Found a workaround / fix.

Lot's of stuff on the web about settings in .config/powerdevilrc (or the same file .config/powermanagementprofilesrc), and logind.conf in /etc. None of this worked. It's a setting in .config/kwinoutputconfig.json, but I don't know which one. Creating a new user and closing the lid works, so I tried just copying over their kwinoutputconfig.json file, but this file gets overwritten for some reason after you edit it or on logout or something. So I copied the file over again from the new user and set it read only (chmod 444). Now I can close the lid with an external monitor and the laptop stays awake.
Comment 6 Oded Arbel 2024-07-14 11:08:56 UTC
(In reply to Eric from comment #5)
> Now I can close the lid with an external monitor and the laptop stays
> awake.

The configuration of how powerdevil handles lid-switch when an external monitor is connected (vs. no external monitor) is in System Settings -> Power Management -> [profile] -> When laptop lid is closed, and there's a checkbox "Even when an external monitor is connected" - and should be off by default (due to a workaround for an unrelated bug, I have this turned on and it is marked as "non-default"). So by default Plasma will not sleep when you lid-switch and an external monitor is connected. This is a good default.

The problem here is that when lid-switch is inhibited, and I have no external monitor (or sleeping with external monitor is enabled), Powerdevil ignores the inhibition and sleeps anyway when it gets a lid-switch.