From 81d6ffbdb606e9b793c62613e3b40e54c29d2a37 Mon Sep 17 00:00:00 2001 From: jiangrenhang <492917571@qq.com> Date: Mon, 15 Jun 2026 01:21:27 +0800 Subject: [PATCH] fix(desktop): close CloseTab-Snapshot/DeleteSession race window Move Snapshot() inside the lock before delete(a.tabs, tabID) to prevent a race where DeleteSession removes session files after the tab is unregistered but before the deferred Snapshot writes them back. Fixes #4384. --- desktop/tabs.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/desktop/tabs.go b/desktop/tabs.go index 79169d7271..69c1212b9b 100644 --- a/desktop/tabs.go +++ b/desktop/tabs.go @@ -1251,6 +1251,14 @@ func (a *App) CloseTab(tabID string) error { a.mu.Unlock() return fmt.Errorf("cannot close the last tab") } + // Snapshot the session state before removing the tab from a.tabs. + // This closes a race window with DeleteSession: if Snapshot runs + // after delete(a.tabs, tabID), a concurrent DeleteSession can delete + // the session files, and the deferred Snapshot recreates them. + if tab.Ctrl != nil { + _ = tab.Ctrl.Snapshot() + } + ordered := a.orderedTabIDsLocked() closedIndex := -1 for i, id := range ordered { @@ -1280,7 +1288,6 @@ func (a *App) CloseTab(tabID string) error { // Tear down outside the lock. if tab.Ctrl != nil { - _ = tab.Ctrl.Snapshot() if tab.hasActiveRuntimeWork() && a.detachSessionRuntime(tab) { return nil }