Attempt to improve the watchdog because it has failed on some systems.

This commit is contained in:
Storm Dragon
2026-09-14 08:23:49 -04:00
parent 02e8472147
commit fc08e505b2
+63 -31
View File
@@ -17,9 +17,40 @@
checkInterval=3 # Check every 3 seconds
timeoutSeconds=2 # Consider i3 locked if it doesn't respond within 2 seconds
pidFile="${HOME}/.config/i3/i3_watchdog.pid"
logFile="/tmp/i38-i3-watchdog-${UID}.log"
maxLogBytes=262144
rotate_log() {
local logSize
[[ -f "$logFile" ]] || return 0
logSize=$(wc -c < "$logFile")
if ((logSize >= maxLogBytes)); then
mv -f -- "$logFile" "${logFile}.old"
fi
}
log_message() {
echo "[i3-watchdog] $*"
local message
message="[i3-watchdog] $* - $(date '+%Y-%m-%d %H:%M:%S')"
rotate_log
printf '%s\n' "$message"
printf '%s\n' "$message" >> "$logFile"
}
check_health() {
ipcWorks=0
focusWorks=0
if timeout "$timeoutSeconds" i3-msg -t get_version > /dev/null 2>&1; then
ipcWorks=1
fi
if timeout 1 xdotool getwindowfocus > /dev/null 2>&1; then
focusWorks=1
fi
}
# Kill any existing watchdog instances
@@ -50,17 +81,7 @@ while true; do
fi
# Try to communicate with i3 IPC AND check X focus
ipcWorks=0
focusWorks=0
if timeout "$timeoutSeconds" i3-msg -t get_version > /dev/null 2>&1; then
ipcWorks=1
fi
# Also check if X focus is working (use current DISPLAY, not hardcoded)
if timeout 1 xdotool getwindowfocus > /dev/null 2>&1; then
focusWorks=1
fi
check_health
# Both must work for system to be healthy
if [[ $ipcWorks -eq 1 ]] && [[ $focusWorks -eq 1 ]]; then
@@ -101,7 +122,7 @@ while true; do
fi
# Try to get i3 socket info
i3Socket=$(i3 --get-socketpath 2>/dev/null)
i3Socket=$(timeout "$timeoutSeconds" i3 --get-socketpath 2>/dev/null)
log_message "i3 socket path: $i3Socket"
if [[ -n "$i3Socket" ]] && [[ -S "$i3Socket" ]]; then
@@ -112,43 +133,54 @@ while true; do
fi
# Check if this is a focus issue (Wine keyboard grab bug)
focusCheck=$(xdotool getwindowfocus 2>&1)
focusCheck=$(timeout 1 xdotool getwindowfocus 2>&1)
log_message "Focus check result: $focusCheck"
# Try to reset focus to i3
log_message "Attempting to reset X focus..."
xdotool key --clearmodifiers Super_L 2>/dev/null
timeout 1 xdotool key --clearmodifiers Super_L 2>/dev/null
sleep 0.5
# Try to focus on i3's root window
i3RootWindow=$(xdotool search --class "i3" | head -1)
i3RootWindow=$(timeout 1 xdotool search --class "i3" 2>/dev/null | head -1)
if [[ -n "$i3RootWindow" ]]; then
log_message "Focusing i3 root window: $i3RootWindow"
xdotool windowfocus "$i3RootWindow" 2>/dev/null
timeout 1 xdotool windowfocus "$i3RootWindow" 2>/dev/null
fi
# Try i3-msg to focus something
log_message "Using i3-msg to focus workspace..."
i3-msg workspace number 1 >/dev/null 2>&1
timeout "$timeoutSeconds" i3-msg workspace number 1 >/dev/null 2>&1
sleep 0.5
i3-msg focus output primary >/dev/null 2>&1
timeout "$timeoutSeconds" i3-msg focus output primary >/dev/null 2>&1
sleep 1
# Check if focus is actually fixed now
if timeout 1 xdotool getwindowfocus >/dev/null 2>&1; then
log_message "Focus recovery successful!"
# Recovery is successful only if both i3 IPC and X focus work.
check_health
if [[ $ipcWorks -eq 1 ]] && [[ $focusWorks -eq 1 ]]; then
log_message "Recovery successful"
lastSuccessTime=$(date +%s)
consecutiveFailures=0
else
log_message "Focus still broken - restarting i3..."
i3-msg -t run_command restart
log_message "Restart command sent"
log_message "Recovery incomplete - IPC:$ipcWorks Focus:$focusWorks; restarting i3"
if timeout "$timeoutSeconds" i3-msg -t run_command restart >/dev/null 2>&1; then
log_message "Restart command accepted"
else
log_message "Restart command failed or timed out"
fi
# Wait for restart to complete, then verify it actually recovered.
sleep 5
check_health
if [[ $ipcWorks -eq 1 ]] && [[ $focusWorks -eq 1 ]]; then
log_message "i3 healthy after restart"
lastSuccessTime=$(date +%s)
consecutiveFailures=0
else
log_message "i3 still unhealthy after restart - IPC:$ipcWorks Focus:$focusWorks"
fi
fi
# Wait for restart to complete
sleep 5
# Reset counters
lastSuccessTime=$(date +%s)
consecutiveFailures=0
fi
fi
done