diff --git a/gitstatus/gitstatus.plugin.zsh b/gitstatus/gitstatus.plugin.zsh index b74396d3..cbd1a2e7 100644 --- a/gitstatus/gitstatus.plugin.zsh +++ b/gitstatus/gitstatus.plugin.zsh @@ -475,6 +475,21 @@ function _gitstatus_daemon"${1:-}"() { kill -- -$pgid fi } &! + + # Parent process monitor: detect orphaning and cleanup + # This handles cases where zshexit hook doesn't fire (e.g., tmux kill-session) + { + local orig_ppid=$sysparams[ppid] + while true; do + command sleep 2 + # If PPID changed to 1 (init/launchd), parent died - cleanup and exit + if [[ $sysparams[ppid] != $orig_ppid ]]; then + zf_rm -f -- $file_prefix.lock $file_prefix.fifo + kill -- -$pgid 2>/dev/null + break + fi + done + } &! } # Starts gitstatusd in the background. Does nothing and succeeds if gitstatusd is already running. diff --git a/internal/worker.zsh b/internal/worker.zsh index 269e8aad..beb34d58 100644 --- a/internal/worker.zsh +++ b/internal/worker.zsh @@ -12,6 +12,9 @@ function _p9k_worker_main() { local -A _p9k_worker_fds # fd => id$'\x1f'callback local -A _p9k_worker_inflight # id => inflight count + # Store original parent PID to detect orphaning + local -i _p9k_worker_orig_ppid=$sysparams[ppid] + function _p9k_worker_reply() { print -nr -- e${(pj:\n:)@}$'\x1e' || kill -- -$_p9k_worker_pgid } @@ -24,10 +27,16 @@ function _p9k_worker_main() { _p9k_worker_fds[$fd]=$_p9k_worker_request_id$'\x1f'$2 } + # Check if parent process is still alive (not orphaned) + # If PPID changes to 1 (init/launchd), parent has died + function _p9k_worker_check_parent() { + [[ $sysparams[ppid] == $_p9k_worker_orig_ppid ]] + } + trap '' PIPE { - while zselect -a ready 0 ${(k)_p9k_worker_fds}; do + while _p9k_worker_check_parent && zselect -a ready 0 ${(k)_p9k_worker_fds}; do [[ $ready[1] == -r ]] || return for fd in ${ready:1}; do if [[ $fd == 0 ]]; then