gamemode-watch: single-instance flock guard

Prevents a manually-launched watcher and the spawn-at-startup one from
racing the same winwatch source; the second instance exits immediately.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
funman300
2026-07-15 21:54:17 -07:00
parent 0ab08e8561
commit 3d08abb060
+18
View File
@@ -10,7 +10,9 @@ Launched at niri startup (spawn-at-startup "gamemode-watch"). Reconnects if the
event stream drops while niri is still alive, and always releases the source on event stream drops while niri is still alive, and always releases the source on
exit so gamemode can never get stuck on when the watcher stops. exit so gamemode can never get stuck on when the watcher stops.
""" """
import fcntl
import json import json
import os
import re import re
import signal import signal
import subprocess import subprocess
@@ -133,7 +135,23 @@ def _on_sigterm(signum, frame):
raise KeyboardInterrupt raise KeyboardInterrupt
def acquire_single_instance():
# Hold an exclusive lock so a second watcher (e.g. spawn-at-startup plus a
# manual launch) exits instead of racing the same winwatch source. The open
# file must stay referenced for the process lifetime to keep the lock.
rt = os.environ.get("XDG_RUNTIME_DIR", "/tmp")
f = open(os.path.join(rt, "gamemode-watch.lock"), "w")
try:
fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
except OSError:
return None
return f
if __name__ == "__main__": if __name__ == "__main__":
_lock = acquire_single_instance()
if _lock is None:
sys.exit(0) # another instance already running
signal.signal(signal.SIGTERM, _on_sigterm) signal.signal(signal.SIGTERM, _on_sigterm)
try: try:
main() main()