nix-git/examples/suspend-impossible.nix

91 lines
3.2 KiB
Nix

{ config, pkgs, lib, ... }:
# Relevant references:
# How to prevent systemd suspend from stopping any service with a dont-sleep.service. https://askubuntu.com/q/830442/1002706
# systemctl show test-block-suspend.service -p TimeoutStopUSec
#=> TimeoutStopUSec=infinity
# systemctl cat test-block-suspend.service
# systemctl list-dependencies --before test-block-suspend.service
#=> test-block-suspend.service
#=> ├─shutdown.target
#=> ├─sleep.target
#=> │ ├─systemd-hibernate.service
#=> │ ├─systemd-hybrid-sleep.service
#=> │ ├─systemd-suspend-then-hibernate.service
#=> │ └─systemd-suspend.service
#=> └─suspend.target
#=> └─post-resume.service
{
# Alternative approach to adding `conflicts`, `before` and `ExecStop`.
#
# Immediately before entering system suspend, all executables in /usr/lib/systemd/system-sleep/ are run.
# Execution of the sleep action is not continued until all have finished.
# TODO: This happens after my screen got blank, wifi disabled, screen locker activated, etc.
# environment.etc."systemd/system-sleep/test-block-suspend".source =
# pkgs.writeShellScript "test-block-suspend" ''
# set -eu -o pipefail
# if [ "$1" == "pre" ]; then
# while :; do
# systemctl is-active --quiet test-block-suspend.service || exit 0
# ${pkgs.coreutils}/bin/echo 'Waiting until service has finished ...'
# ${pkgs.coreutils}/bin/sleep 1s
# done
# fi
# '';
systemd.services."test-block-suspend" = {
description = "Inhibit suspend";
# If suspend is initiated, this service is stopped.
conflicts = [ "sleep.target" ];
# Start-up of `sleep.target`
# is delayed until this service has finished starting up.
before = [ "sleep.target" ];
serviceConfig = {
# `simple`:
# As soon as the main process (defined in the `ExecStart`) is started (forked),
# start-up is considered as finished.
# `notify`:
# The service sends a "READY=1" notification message via `sd_notify` when it has finished starting up.
# Requires `NotifyAccess`.
# See https://www.freedesktop.org/software/systemd/man/latest/systemd-notify.html
Type = "notify";
NotifyAccess = "main";
# To stop this service `ExecStop` is run instead of sending SIGTERM to the main process of the service.
# The command specified by `ExecStop` does never end,
# thus stopping this service takes forever.
# TODO: However, the sleep action continues while `ExecStop` is running. As a reslut, the system suspends.
ExecStop = "${pkgs.coreutils}/bin/sleep infinity";
TimeoutStopSec = "infinity";
# This service executes a shell script as main process.
ExecStart = pkgs.writeShellScript "test-block-suspend-execstart" ''
set -eu -o pipefail
#handle_sigterm(){
# #while :; do
# printf '%s\n' 'Ignoring SIGTERM ...' >&2
# # ${pkgs.coreutils}/bin/sleep 5s
# #done
#}
#trap 'handle_sigterm' TERM
#printf '%s\n' 'Start-up 30s ...'
#${pkgs.coreutils}/bin/sleep 30s
systemd-notify READY=1
while :; do
printf '%s\n' 'Still alive'
${pkgs.coreutils}/bin/sleep 5s
done
'';
};
};
}