Make a dead lock client diagnosable and recoverable (#6630)
* Persist the Omarchy shell log across sessions Quickshell only logs to its instance runtime dir on tmpfs, so when the shell dies the idle/lock event trail is gone after a reboot (#6628). Launch the shell through omarchy-launch-shell, which pipes stdout/stderr into the journal under the omarchy-shell tag — bounded, timestamped, and persistent — and surface that log in omarchy-debug-idle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Recover a locked session whose lock client died When the shell dies while the session is locked, Hyprland's failsafe keeps the session locked with no lock client left, and omarchy-restart-shell refused to run in exactly that state, leaving reboot as the only way back in (#6628). Gate the refusal on the lock service actually holding (or acquiring) the lock rather than on the session's LOCK state — a dead shell and a crash-handler relaunch that holds no lock both fail that check — then restart the shell, re-acquire the session lock, and wait for it to report secure, the same secure-poll omarchy-system-sleep-lock uses, so the user can authenticate out of the failsafe. Enable Hyprland's allow_session_lock_restore so the compositor accepts the replacement lock client. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
3aa7c1ee13
commit
1ded25fd45
@@ -27,6 +27,9 @@ section "Recent idle logs"
|
||||
quickshell --no-color log -p "$OMARCHY_PATH/shell" --any-display --tail "$lines" --log-times -r 'quickshell.wayland.idle_notify=true' 2>&1 \
|
||||
| grep -Ei 'omarchy idle|idle_notify|screensaver|lock|error|warn|failed' || true
|
||||
|
||||
section "Persisted shell log"
|
||||
journalctl -t omarchy-shell -n "$lines" --no-pager --quiet 2>/dev/null || true
|
||||
|
||||
section "Relevant processes"
|
||||
ps -eo pid=,args= \
|
||||
| grep -E 'quickshell -n -p|omarchy-system-sleep-monitor|systemd-inhibit.*Lock screen before suspend|org\.omarchy\.screensaver|omarchy-screensaver|(^|/| )tte( |$)' \
|
||||
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Launch the Omarchy shell with its log kept in the journal
|
||||
# omarchy:hidden=true
|
||||
|
||||
# Quickshell only logs to its instance runtime dir (tmpfs), so when the shell
|
||||
# dies the idle/lock event trail is gone after a reboot. The journal keeps it
|
||||
# across sessions, bounded and timestamped, under the omarchy-shell tag.
|
||||
exec systemd-cat -t omarchy-shell -- quickshell -n -p "$OMARCHY_PATH/shell"
|
||||
@@ -18,11 +18,49 @@ if [[ -z ${HYPRLAND_INSTANCE_SIGNATURE:-} ]]; then
|
||||
[[ -n $hypr_dir ]] && export HYPRLAND_INSTANCE_SIGNATURE=${hypr_dir##*/}
|
||||
fi
|
||||
|
||||
# Restarting a live lock client would kill the lock screen and strand the
|
||||
# session behind Hyprland's failsafe. But a LOCK session without an active
|
||||
# locker — the shell died, or its crash handler re-execed a fresh instance
|
||||
# that holds no lock — sits in that failsafe with no way to authenticate,
|
||||
# and a restart plus re-lock is the only way back in without a reboot. So
|
||||
# ask the lock service rather than merely pinging the shell: only a locker
|
||||
# that reports the lock secure or in progress is worth preserving.
|
||||
relock=0
|
||||
if [[ $(hyprctl -j monitors 2>/dev/null) == *'"LOCK"'* ]]; then
|
||||
echo "Refusing to restart Omarchy shell while the session is locked." >&2
|
||||
exit 1
|
||||
locking=$(OMARCHY_PATH="$session_omarchy_path" OMARCHY_SHELL_IPC_TIMEOUT=0.5s omarchy-shell lock status 2>/dev/null |
|
||||
jq -r '.secure or .requested' 2>/dev/null)
|
||||
if [[ $locking == "true" ]]; then
|
||||
echo "Refusing to restart Omarchy shell while the session is locked." >&2
|
||||
exit 1
|
||||
fi
|
||||
relock=1
|
||||
fi
|
||||
|
||||
# The lock plugin loads asynchronously, so a fresh shell answers ping before
|
||||
# it can lock, and may even refuse early lock requests while its plugins or
|
||||
# PAM config are still loading. Mirror omarchy-system-sleep-lock: request the
|
||||
# lock and poll until the session reports secure, re-requesting as needed, so
|
||||
# recovery never claims success while the failsafe is still up. The deadline
|
||||
# is generous because slow plugin discovery delays the lock IPC target.
|
||||
relock_session() {
|
||||
local state deadline=$((SECONDS + 30))
|
||||
|
||||
while (( SECONDS < deadline )); do
|
||||
state=$(OMARCHY_PATH="$session_omarchy_path" OMARCHY_SHELL_IPC_TIMEOUT=0.5s omarchy-shell lock status 2>/dev/null |
|
||||
jq -r 'if .secure == true then "secure" elif .requested == true then "locking" else "idle" end' 2>/dev/null)
|
||||
|
||||
case $state in
|
||||
secure) return 0 ;;
|
||||
locking) ;;
|
||||
*) OMARCHY_PATH="$session_omarchy_path" OMARCHY_SHELL_IPC_TIMEOUT=0.5s omarchy-shell lock lock >/dev/null 2>&1 ;;
|
||||
esac
|
||||
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Each kill stops the oldest matching instance and only returns once it has
|
||||
# fully exited, so the no-duplicate launch below can't race a dying shell.
|
||||
# Requires our quickshell-git build; 0.3.0's kill returns immediately.
|
||||
@@ -30,10 +68,16 @@ while timeout 5 quickshell kill -p "$CONFIG_DIR" --any-display >/dev/null 2>&1;
|
||||
|
||||
# Spawn from Hyprland so the shell inherits the canonical session environment,
|
||||
# not transient variables from a terminal, SSH connection, or development tool.
|
||||
hyprctl dispatch 'hl.dsp.exec_cmd("quickshell -n -p $OMARCHY_PATH/shell")' >/dev/null
|
||||
hyprctl dispatch 'hl.dsp.exec_cmd("omarchy-launch-shell")' >/dev/null
|
||||
|
||||
for (( attempt = 0; attempt < 20; attempt++ )); do
|
||||
if OMARCHY_PATH="$session_omarchy_path" OMARCHY_SHELL_IPC_TIMEOUT=0.5s omarchy-shell shell ping >/dev/null 2>&1; then
|
||||
# The session stays compositor-locked after the old lock client died, so
|
||||
# re-acquire the lock and let the user authenticate out of it.
|
||||
if (( relock )) && ! relock_session; then
|
||||
echo "Omarchy shell restarted, but the session lock was not re-secured." >&2
|
||||
exit 1
|
||||
fi
|
||||
# Invitation toasts (like Voxtype/fingerprint setup) die with the old
|
||||
# shell, and their notify-send waiters hang forever: the dying server
|
||||
# never emits NotificationClosed. A still-running omarchy-*-invitation
|
||||
|
||||
Reference in New Issue
Block a user