Replace crash guard with SIGUSR1 unlock and crash logging

Remove sys.excepthook that unlocked on crash — this violated
ext-session-lock-v1 security model where the compositor must keep
the screen locked if the client dies (per protocol spec and hyprlock
reference). Now: crashes are logged but session stays locked.
SIGUSR1 handler added for external recovery (e.g. wrapper script).
This commit is contained in:
2026-03-26 21:11:42 +01:00
parent 3f31387305
commit 5fda0dce0c
3 changed files with 48 additions and 48 deletions
+20 -15
View File
@@ -112,8 +112,7 @@ class MoonlockApp(Gtk.Application):
logger.exception("Failed to create lockscreen window for monitor %d", i)
if not self._windows:
logger.critical("No lockscreen windows created — unlocking session to prevent lockout")
self._lock_instance.unlock()
logger.critical("No lockscreen windows created — screen stays locked (compositor policy)")
def _activate_without_lock(self) -> None:
"""Fallback for development — no session lock, just a window."""
@@ -146,20 +145,26 @@ class MoonlockApp(Gtk.Application):
logger.exception("Failed to load CSS stylesheet")
def _install_crash_guard(app: MoonlockApp) -> None:
"""Install a global exception handler that unlocks the session on crash."""
_original_excepthook = sys.excepthook
def _install_signal_handlers(app: MoonlockApp) -> None:
"""Install signal handlers for external unlock (SIGUSR1) and crash logging."""
import signal
from gi.repository import GLib
def _crash_guard(exc_type, exc_value, exc_tb):
logger.critical("Unhandled exception — unlocking session to prevent lockout", exc_info=(exc_type, exc_value, exc_tb))
if app._lock_instance:
try:
app._lock_instance.unlock()
except Exception:
pass
_original_excepthook(exc_type, exc_value, exc_tb)
def _handle_unlock(signum, frame):
"""SIGUSR1: External unlock request (e.g. from recovery wrapper)."""
logger.info("Received SIGUSR1 — unlocking session")
GLib.idle_add(app._unlock)
sys.excepthook = _crash_guard
def _handle_crash_log(signum, frame):
"""Log unhandled exceptions but do NOT unlock — compositor keeps screen locked."""
logger.critical("Unhandled exception in moonlock", exc_info=True)
signal.signal(signal.SIGUSR1, _handle_unlock)
sys.excepthook = lambda exc_type, exc_value, exc_tb: (
logger.critical("Unhandled exception — screen stays locked (compositor policy)",
exc_info=(exc_type, exc_value, exc_tb)),
sys.__excepthook__(exc_type, exc_value, exc_tb),
)
def main() -> None:
@@ -167,7 +172,7 @@ def main() -> None:
_setup_logging()
logger.info("Moonlock starting")
app = MoonlockApp()
_install_crash_guard(app)
_install_signal_handlers(app)
app.run(sys.argv)