From f98b12579e7b02108bb03fc9d75d8fecef82ca7e Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 5 Dec 2025 08:30:33 -0800 Subject: [PATCH] core: selection and copy bindings need to hold the big lock This was found by LLM hunting! We were not holding the lock properly during these operations. There aren't any known cases where we can directly attribute these races to issues but we did find at least one consistent crash for a user when `linkAtPos` wasn't properly locked (in another PR). This continues those fixes. --- src/Surface.zig | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Surface.zig b/src/Surface.zig index 1926c4394..653178bdc 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -5032,8 +5032,9 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool }, .copy_to_clipboard => |format| { - // We can read from the renderer state without holding - // the lock because only we will write to this field. + self.renderer_state.mutex.lock(); + defer self.renderer_state.mutex.unlock(); + if (self.io.terminal.screens.active.selection) |sel| { try self.copySelectionToClipboards( sel, @@ -5061,8 +5062,10 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool .copy_url_to_clipboard => { // If the mouse isn't over a link, nothing we can do. if (!self.mouse.over_link) return false; - const pos = try self.rt_surface.getCursorPos(); + + self.renderer_state.mutex.lock(); + defer self.renderer_state.mutex.unlock(); if (try self.linkAtPos(pos)) |link_info| { const url_text = switch (link_info[0]) { .open => url_text: { @@ -5438,6 +5441,9 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool ), .select_all => { + self.renderer_state.mutex.lock(); + defer self.renderer_state.mutex.unlock(); + const sel = self.io.terminal.screens.active.selectAll(); if (sel) |s| { try self.setSelection(s);