Release sleep inhibitor after locking (#6436)

This commit is contained in:
David Heinemeier Hansson
2026-07-29 23:21:45 -04:00
committed by GitHub
parent 8554801537
commit e47d895ffe
2 changed files with 142 additions and 8 deletions
+36 -8
View File
@@ -4,8 +4,6 @@
# omarchy:group=system # omarchy:group=system
# omarchy:hidden=true # omarchy:hidden=true
monitor_command='exec dbus-monitor --system "type='\''signal'\'',sender='\''org.freedesktop.login1'\'',interface='\''org.freedesktop.login1.Manager'\'',member='\''PrepareForSleep'\''"'
consume_sleep_events() { consume_sleep_events() {
local line sleep_lock local line sleep_lock
sleep_lock="$OMARCHY_PATH/bin/omarchy-system-sleep-lock" sleep_lock="$OMARCHY_PATH/bin/omarchy-system-sleep-lock"
@@ -13,15 +11,45 @@ consume_sleep_events() {
while IFS= read -r line; do while IFS= read -r line; do
if [[ $line == *"boolean true"* ]]; then if [[ $line == *"boolean true"* ]]; then
"$sleep_lock" "$sleep_lock"
exit 0 return 0
fi fi
done done
} }
if [[ ${1:-} == "--consume" ]]; then monitor_sleep_events() {
consume_sleep_events local monitor_fd monitor_pid status
exit 0
fi coproc SLEEP_EVENTS {
exec dbus-monitor --system \
"type='signal',sender='org.freedesktop.login1',interface='org.freedesktop.login1.Manager',member='PrepareForSleep'"
}
monitor_fd=${SLEEP_EVENTS[0]}
monitor_pid=$SLEEP_EVENTS_PID
cleanup_monitor() {
kill "$monitor_pid" 2>/dev/null || true
wait "$monitor_pid" 2>/dev/null || true
}
trap cleanup_monitor EXIT
consume_sleep_events <&"$monitor_fd"
status=$?
cleanup_monitor
trap - EXIT
return "$status"
}
case ${1:-} in
--consume)
consume_sleep_events
exit 0
;;
--inhibited)
monitor_sleep_events
exit 0
;;
esac
sleep_monitor="$OMARCHY_PATH/bin/omarchy-system-sleep-monitor" sleep_monitor="$OMARCHY_PATH/bin/omarchy-system-sleep-monitor"
@@ -30,4 +58,4 @@ exec systemd-inhibit \
--mode=delay \ --mode=delay \
--who=Omarchy \ --who=Omarchy \
--why="Lock screen before suspend" \ --why="Lock screen before suspend" \
bash -lc "$monitor_command | \"$sleep_monitor\" --consume" "$sleep_monitor" --inhibited
+106
View File
@@ -0,0 +1,106 @@
#!/bin/bash
set -euo pipefail
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
sleep_monitor="$ROOT/bin/omarchy-system-sleep-monitor"
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
mock_bin="$tmpdir/bin"
mock_omarchy="$tmpdir/omarchy"
producer_pid_file="$tmpdir/producer-pid"
lock_log="$tmpdir/lock-log"
mkdir -p "$mock_bin" "$mock_omarchy/bin"
cat >"$mock_bin/systemd-inhibit" <<'SH'
#!/bin/bash
while [[ $1 == --* ]]; do
shift
done
exec "$@"
SH
cat >"$mock_bin/dbus-monitor" <<'SH'
#!/bin/bash
echo "$$" >"$PRODUCER_PID_FILE"
printf ' boolean true\n'
exec sleep 30
SH
cat >"$mock_omarchy/bin/omarchy-system-sleep-lock" <<'SH'
#!/bin/bash
echo locked >>"$LOCK_LOG"
SH
chmod +x \
"$mock_bin/systemd-inhibit" \
"$mock_bin/dbus-monitor" \
"$mock_omarchy/bin/omarchy-system-sleep-lock"
ln -s "$sleep_monitor" "$mock_omarchy/bin/omarchy-system-sleep-monitor"
start_us=${EPOCHREALTIME//[!0-9]/}
OMARCHY_PATH="$mock_omarchy" \
PATH="$mock_bin:$PATH" \
PRODUCER_PID_FILE="$producer_pid_file" \
LOCK_LOG="$lock_log" \
"$sleep_monitor"
elapsed_us=$((10#${EPOCHREALTIME//[!0-9]/} - 10#$start_us))
[[ $(<"$lock_log") == "locked" ]] ||
fail "sleep monitor invokes the lock helper for a sleep event"
pass "sleep monitor invokes the lock helper for a sleep event"
(( elapsed_us < 2000000 )) ||
fail "sleep monitor releases the inhibitor after locking" "elapsed: ${elapsed_us}us"
pass "sleep monitor releases the inhibitor after locking"
producer_pid=$(<"$producer_pid_file")
if kill -0 "$producer_pid" 2>/dev/null; then
fail "sleep monitor reaps its event producer" "producer still running: $producer_pid"
fi
pass "sleep monitor reaps its event producer"
# Terminating the monitor must also clean up the producer instead of orphaning
# it under the user systemd instance.
cat >"$mock_bin/dbus-monitor" <<'SH'
#!/bin/bash
sleep 0.1
echo "$$" >"$PRODUCER_PID_FILE"
exec sleep 30
SH
chmod +x "$mock_bin/dbus-monitor"
rm -f "$producer_pid_file"
OMARCHY_PATH="$mock_omarchy" \
PATH="$mock_bin:$PATH" \
PRODUCER_PID_FILE="$producer_pid_file" \
LOCK_LOG="$lock_log" \
"$sleep_monitor" &
monitor_pid=$!
for _ in {1..100}; do
[[ -s $producer_pid_file ]] && break
sleep 0.01
done
if [[ ! -s $producer_pid_file ]]; then
kill "$monitor_pid" 2>/dev/null || true
wait "$monitor_pid" 2>/dev/null || true
fail "sleep monitor starts its event producer"
fi
producer_pid=$(<"$producer_pid_file")
kill "$monitor_pid"
wait "$monitor_pid" 2>/dev/null || true
if kill -0 "$producer_pid" 2>/dev/null; then
kill "$producer_pid" 2>/dev/null || true
fail "sleep monitor cleans up its producer when terminated" "producer still running: $producer_pid"
fi
pass "sleep monitor cleans up its producer when terminated"