fix(frame-timing): keep the GC monitor quiet at interpreter shutdown (#734)

A collection during interpreter shutdown called GcMonitor after the
module's `time` global was torn down, printing "Exception ignored while
calling GC callback ... 'NoneType' object has no attribute
'perf_counter'" at the end of service and test runs.

- GcMonitor binds its clock and sys.is_finalizing at construction and
  does nothing once the interpreter is finalizing.
- install_gc_monitor() unregisters it with atexit; new
  uninstall_gc_monitor().
- DisplayManager.cleanup() (reached from SIGTERM via run()'s finally)
  unregisters it alongside the frame recorder.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Chuck
2026-10-03 11:51:06 -04:00
committed by GitHub
co-authored by Claude Opus 5.5
parent a5ec645d25
commit 76ad71d1c5
5 changed files with 133 additions and 5 deletions
+4 -1
View File
@@ -57,7 +57,8 @@ import freetype
from src.common import snapshot_policy
from src import display_watchdog
from src.common.frame_timing import FrameTimingRecorder, install_gc_monitor
from src.common.frame_timing import (
FrameTimingRecorder, install_gc_monitor, uninstall_gc_monitor)
if TYPE_CHECKING:
from src.common.render_gate import RenderGate
@@ -1407,6 +1408,8 @@ class DisplayManager:
# The stall watchdog would otherwise outlive this manager.
if getattr(self, 'frame_timing', None) is not None:
self.frame_timing.close()
# Installed with the recorder; stop timing collections with it.
uninstall_gc_monitor()
# Reset the singleton state when cleaning up
DisplayManager._instance = None