From 25e62456914392344bc6d7e3bbd9fb5a3a50fbc5 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 9 Jul 2026 10:47:31 -0700 Subject: [PATCH] renderer: avoid starving scrollback compression Inspector rendering can hold the terminal mutex while waking the renderer. When the compression scheduler failed to acquire that mutex, it treated every wake as possible terminal activity and restarted the idle timer. Frequent inspector frames could therefore postpone compression indefinitely until another interaction changed the timing. Keep an existing compression deadline when a wake encounters lock contention. The timer callback already rechecks both terminal activity and lock availability, while the first contended wake still arms a timer when none is active. --- src/renderer/Thread.zig | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/renderer/Thread.zig b/src/renderer/Thread.zig index 7f93e9493..e397a55a1 100644 --- a/src/renderer/Thread.zig +++ b/src/renderer/Thread.zig @@ -792,10 +792,17 @@ const Compression = struct { const activity = thread.state.terminal.compressionActivity(); if (self.activity == activity) return; self.activity = activity; + } else if (self.completion.state() == .active) { + // Contention doesn't prove that compression-relevant activity + // changed. Keep an existing deadline so frequent inspector frames + // cannot postpone compression forever. The timer rechecks both the + // activity token and lock availability before doing any work. + return; } // Contention may mean parsing is active. Scheduling is a harmless - // false positive when no compression work is actually pending. + // false positive when no compression work is actually pending, but is + // necessary when no timer is already active. self.schedule(thread, idle_interval); }