aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/dot_local
diff options
context:
space:
mode:
authorLibravatar sommerfeld <sommerfeld@sommerfeld.dev>2026-05-29 11:18:14 +0100
committerLibravatar sommerfeld <sommerfeld@sommerfeld.dev>2026-05-29 11:18:14 +0100
commit0711f1b4a4045c583c63f494a61262ed1146a944 (patch)
treed58a14e6448e11de5510aedafe5cce1150a91637 /dot_local
parent5ee66a0415e88f4fa78986c823dd1ad709524e70 (diff)
downloaddotfiles-0711f1b4a4045c583c63f494a61262ed1146a944.tar.gz
dotfiles-0711f1b4a4045c583c63f494a61262ed1146a944.tar.bz2
dotfiles-0711f1b4a4045c583c63f494a61262ed1146a944.zip
fix(suspend): only inhibit for SSH-spawned zellij sessions
A local zellij session (sway terminal, attended) shouldn't keep the laptop awake — that's the user actively in front of the machine, and normal suspend behaviour should apply. Only zellij sessions that were spawned from an SSH context need the persistent inhibit, so detach + disconnect leaves the host awake until the session ends. Use /proc/<pid>/environ to detect SSH-spawned zellij: the daemonised zellij server is exec'd by the client and Linux preserves the exec-time environment for the life of the process, so SSH_CONNECTION= survives the SSH session closing. Walk every running `zellij` pid; hold the lock as long as at least one of them has SSH_CONNECTION in its environ. The .path unit still fires on every zellij socket creation, but if no SSH-spawned zellij exists the watcher exits immediately and the service stops with no harm done — a couple of cheap process spawns per local session start, no inhibitor side-effects.
Diffstat (limited to 'dot_local')
-rwxr-xr-xdot_local/bin/executable_zellij-inhibit-watcher41
1 files changed, 30 insertions, 11 deletions
diff --git a/dot_local/bin/executable_zellij-inhibit-watcher b/dot_local/bin/executable_zellij-inhibit-watcher
index 0af20dd..6af7032 100755
--- a/dot_local/bin/executable_zellij-inhibit-watcher
+++ b/dot_local/bin/executable_zellij-inhibit-watcher
@@ -1,20 +1,39 @@
#!/bin/sh
-# Block until no zellij sessions remain.
+# Block while at least one zellij server process was spawned from an
+# SSH context, exit cleanly once none remain.
#
-# Used as the ExecStart payload of zellij-inhibit-suspend.service: the
-# service wraps this script with `systemd-inhibit`, so the inhibit lock
-# is held for exactly the lifetime of this process. When the last zellij
-# session ends, this script exits 0, the service stops, and the lock is
-# released.
+# Rationale: a zellij session started locally (e.g. from a sway terminal)
+# is the user actively sitting in front of the laptop — that should NOT
+# inhibit suspend. Only zellij sessions started while SSH'd in deserve
+# the lock, so the host stays awake across detach + disconnect but
+# normal local-attended suspend still works.
#
-# A user-level `.path` unit re-activates the service whenever the zellij
-# socket directory becomes non-empty again, so the lock is automatically
-# reacquired on the next `zellij` invocation.
+# Detection: zellij's daemonised server is exec'd by the client and
+# inherits the client's environment. Linux preserves that exec-time
+# environment in /proc/<pid>/environ for the life of the process, even
+# after the original SSH session is gone. So an "ssh-spawned" zellij is
+# one whose environ contains SSH_CONNECTION=.
+#
+# This script is the ExecStart payload of zellij-inhibit-suspend.service,
+# which wraps it in systemd-inhibit. When this script exits, the lock is
+# released. The .path unit re-fires the service on the next zellij socket
+# transition.
set -eu
poll=${ZELLIJ_INHIBIT_POLL:-15}
-while sessions=$(zellij list-sessions --short 2>/dev/null) &&
- [ -n "$sessions" ]; do
+has_ssh_zellij() {
+ pids=$(pgrep -x zellij 2>/dev/null) || return 1
+ for pid in $pids; do
+ [ -r "/proc/$pid/environ" ] || continue
+ if tr '\0' '\n' <"/proc/$pid/environ" 2>/dev/null |
+ grep -q '^SSH_CONNECTION='; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+while has_ssh_zellij; do
sleep "$poll"
done