1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-12-22 00:17:37 +02:00

Band-aid fix for rare crashes when refreshing files

Users have filed issues with crash reports that seem to indicate that the
FileTreeViewModel gets swapped out (by a refresh) while a call to itemsSelected
is in progress, iterating over the previous items. Guard against this by locking
the mutex that we already have for this for the duration of the call.

I don't have a good way of testing whether the fix helps, because the crashes
only occurred very infrequently. Let's just see if the crash reports stop coming
in after we ship this.

Note also that this is only the minimal fix for the crashes that were reported.
Theoretically, the same problem could happen for a key handler itself, but we
never saw reports about that, so we don't bother doing anything about that yet.

Note also that long-term I envision a different solution to this class of
problems (discussed in https://github.com/jesseduffield/lazygit/issues/2974),
that's why I want to avoid locking mutexes more than necessary now.
This commit is contained in:
Stefan Haller
2025-11-26 09:25:27 +01:00
parent d1d2bb23b6
commit d274474c61

View File

@@ -44,7 +44,7 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types
{
Key: opts.GetKey(opts.Config.Universal.Select),
Handler: self.withItems(self.press),
GetDisabledReason: self.require(self.itemsSelected()),
GetDisabledReason: self.require(self.withFileTreeViewModelMutex(self.itemsSelected())),
Description: self.c.Tr.Stage,
Tooltip: self.c.Tr.StageTooltip,
DisplayOnScreen: true,
@@ -91,7 +91,7 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types
{
Key: opts.GetKey(opts.Config.Universal.Edit),
Handler: self.withItems(self.edit),
GetDisabledReason: self.require(self.itemsSelected(self.canEditFiles)),
GetDisabledReason: self.require(self.withFileTreeViewModelMutex(self.itemsSelected(self.canEditFiles))),
Description: self.c.Tr.Edit,
Tooltip: self.c.Tr.EditFileTooltip,
DisplayOnScreen: true,
@@ -145,7 +145,7 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types
{
Key: opts.GetKey(opts.Config.Universal.Remove),
Handler: self.withItems(self.remove),
GetDisabledReason: self.require(self.itemsSelected(self.canRemove)),
GetDisabledReason: self.withFileTreeViewModelMutex(self.require(self.itemsSelected(self.canRemove))),
Description: self.c.Tr.Discard,
Tooltip: self.c.Tr.DiscardFileChangesTooltip,
OpensMenu: true,
@@ -182,7 +182,7 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types
Handler: self.withItems(self.openMergeConflictMenu),
Description: self.c.Tr.ViewMergeConflictOptions,
Tooltip: self.c.Tr.ViewMergeConflictOptionsTooltip,
GetDisabledReason: self.require(self.itemsSelected(self.canOpenMergeConflictMenu)),
GetDisabledReason: self.require(self.withFileTreeViewModelMutex(self.itemsSelected(self.canOpenMergeConflictMenu))),
OpensMenu: true,
DisplayOnScreen: true,
},
@@ -209,6 +209,15 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types
}
}
func (self *FilesController) withFileTreeViewModelMutex(callback func() *types.DisabledReason) func() *types.DisabledReason {
return func() *types.DisabledReason {
self.c.Contexts().Files.FileTreeViewModel.RWMutex.RLock()
defer self.c.Contexts().Files.FileTreeViewModel.RWMutex.RUnlock()
return callback()
}
}
func (self *FilesController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding {
return []*gocui.ViewMouseBinding{
{