#!/usr/bin/env bash set -uo pipefail LOGTAG=revive-monitor-drm-watch SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" COMMON="$SCRIPT_DIR/../lib/hyprland-hdmi-revive/common.sh" [[ -f "$COMMON" ]] || COMMON="$SCRIPT_DIR/../lib/common.sh" # shellcheck source=lib/common.sh source "$COMMON" || exit 1 load_config || exit 1 require_commands udevadm stdbuf timeout loginctl flock stat || exit 1 prepare_runtime || exit 1 if [[ -n "${REVIVE_MONITOR_FIX_SCRIPT:-}" ]]; then FIX_SCRIPT="$REVIVE_MONITOR_FIX_SCRIPT" else FIX_SCRIPT="$SCRIPT_DIR/revive-monitor-fix" [[ -e "$FIX_SCRIPT" ]] || FIX_SCRIPT="$SCRIPT_DIR/revive-monitor-fix.sh" fi if [[ ! -x "$FIX_SCRIPT" ]]; then log "Recovery script is not executable: $FIX_SCRIPT" exit 1 fi exec 8>"$STATE_DIR/watcher.lock" || exit 1 if ! flock -n 8; then log 'Another watcher is running or the watcher lock is unavailable' exit 1 fi run_recovery() { local session_info now status session_info="$(get_active_wayland_session)" || { log 'No active Wayland session - DRM hotplug ignored' return 0 } now=$SECONDS if (( last_run >= 0 && now - last_run < DEBOUNCE_SECONDS )); then log 'DRM hotplug ignored because of debounce' return 0 fi log "DRM hotplug detected - Wayland session ${session_info%%:*} on VT ${session_info##*:}" "$FIX_SCRIPT" "${session_info##*:}" status=$? # Measure from completion, so events queued during our own VT refresh are suppressed. last_run=$SECONDS if (( status != 0 )); then log "Recovery after DRM hotplug failed (exit $status)" else log 'Recovery helper finished; see its log for completion or skip reason' fi } log 'Listening for DRM hotplug events' # pipefail propagates a failed producer. EOF (even exit 0) is unexpected for # this long-running service and must also trigger Restart=on-failure. stdbuf -oL udevadm monitor --kernel --property --subsystem-match=drm | while IFS= read -r line; do last_run=${last_run:--1} case "$line" in HOTPLUG=1) run_recovery ;; esac done status=$? log "DRM event stream ended (exit $status) - requesting service restart" exit 1