Attempt to improve the watchdog because it has failed on some systems.
This commit is contained in:
+63
-31
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user