HOWTO Disable Systemd Inhibitors So Suspend And Hibernation Works

From LinuxReviews
Jump to navigationJump to search

The systemd service manager has a class of bugs called "inhibitors" that tend to prevent GNU/Linux laptops from suspending to disk or RAM. The parts of this "feature" can be disabled by creating a special policykit file. Here's how.

Why Would They Do This?

The idea behind inhibitors is to prevent one user on a multi-user system from powering off or suspending a shared server while another user is doing something important. The practical result for the vast majority of people is that their machines fail to hibernate or suspend because some piece of software like a web browser has decided to place a "inhibitor" lock because a paused video is open in a tab or something like that.

The Solution

systemd will ask policykit for permission before a program can place inhibitor locks that prevents basic essential functionality like suspend which Linux desktop users on portable devices like laptop expect. This means that you can make a custom rule file in /etc/polkit-1/rules.d/ that denies anything attempting to prevent suspend/hibernation functionality from working permission to do so.

File: /etc/polkit-1/rules.d/00-disable-inhibitors-and-make-hibernation-work.rules
polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.login1.inhibit-block-shutdown" ||
        action.id == "org.freedesktop.login1.inhibit-block-sleep" ||
        action.id == "org.freedesktop.login1.inhibit-block-idle")
    {
        return polkit.Result.NO;
    }
});

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.login1.inhibit-delay-shutdown" ||
        action.id == "org.freedesktop.login1.inhibit-delay-sleep")
    {
        return polkit.Result.NO;
    }
});

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.login1.power-off-ignore-inhibit" ||
        action.id == "org.freedesktop.login1.reboot-ignore-inhibit" ||
        action.id == "org.freedesktop.login1.halt-ignore-inhibit" ||
        action.id == "org.freedesktop.login1.suspend-ignore-inhibit" ||
        action.id == "org.freedesktop.login1.hibernate-ignore-inhibit")
    {
        return polkit.Result.YES;
    }
});

The last rule-set isn't needed if you want to permanently fix the systemd inhibitor bug using the first two rule-sets.

You can use that last rule-set to allow you to force systemctl to work as it should with systemctl hibernate --check-inhibitors=no from the command line when programs are allowed to set inhibitors. This is of course not a good or practical solution since the expected and practical behavior is that a laptop suspends when the lid is closed or the battery's low every time - not just half the time (which is what you get with inhibitor-bug/"functionality" enabled).


Add your comment
LinuxReviews welcomes all comments. If you do not want to be anonymous, register or log in. It is free.