The Menu Render Guard implemetned to prevent IPC errors after sleep/wake

This commit is contained in:
2026-05-16 11:10:16 -04:00
parent 4b1d6808c9
commit c3308429ff
+14
View File
@@ -34,6 +34,7 @@ obj.saveCountdown = obj.saveInterval
obj.isRescued = false
obj.isTransitioning = false
obj.isRestoring = false
obj.isMenuUpdating = false -- Safety guard to prevent concurrent IPC menu rendering loops
obj.wakeTimer = nil
obj.lastScreenCount = #hs.screen.allScreens()
obj.lastSavedTime = "Never"
@@ -231,6 +232,10 @@ end
local timerMenu = hs.menubar.new()
function updateMenu()
-- Safety Guard: Bail if update is already running from a previous thread block
if obj.isMenuUpdating then return end
obj.isMenuUpdating = true
if timerMenu then
local screens = hs.screen.allScreens()
timerMenu:setTitle(string.format("💠 %d:%02d", math.floor(obj.saveCountdown / 60), obj.saveCountdown % 60))
@@ -257,17 +262,25 @@ function updateMenu()
end
timerMenu:setMenu(menuTable)
end
obj.isMenuUpdating = false
end
obj.powerWatcher = hs.caffeinate.watcher.new(function(event)
if event == hs.caffeinate.watcher.systemWillSleep or event == hs.caffeinate.watcher.screensDidSleep or event == hs.caffeinate.watcher.screensDidLock then
log("POWER: Sleep event.")
obj.isTransitioning = true
-- Stop both timers entirely so they don't fire or stack requests while suspended
if obj.autoSaveTimer then obj.autoSaveTimer:stop() end
if obj.clockTimer then obj.clockTimer:stop() end
elseif event == hs.caffeinate.watcher.systemDidWake or event == hs.caffeinate.watcher.screensDidWake or event == hs.caffeinate.watcher.screensDidUnlock then
log("POWER: Wake event.")
obj.saveCountdown = obj.saveInterval
obj.isMenuUpdating = false -- Explicitly clean guard flag upon waking up
-- Safely start timers up only after wakeup initialization
if obj.autoSaveTimer then obj.autoSaveTimer:start() end
if obj.clockTimer then obj.clockTimer:start() end
if obj.wakeTimer then obj.wakeTimer:stop() end
local currentScreens = #hs.screen.allScreens()
@@ -285,6 +298,7 @@ obj.powerWatcher = hs.caffeinate.watcher.new(function(event)
obj.isTransitioning = false
obj.isRestoring = false
obj.lastScreenCount = currentScreens
updateMenu()
end
end
end):start()