From 5a159ce444f02f8cbb7002d7b7522c2a5b81f505 Mon Sep 17 00:00:00 2001 From: Dmytro Maluka Date: Sun, 12 May 2024 20:35:07 +0200 Subject: [PATCH] updateDiffSync(): fix potential race When updateDiffSync() is called asynchronously, it should lock the line array when calling Bytes(), to prevent race if the line array is being modified by the main goroutine in the meantime. --- internal/buffer/buffer.go | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/internal/buffer/buffer.go b/internal/buffer/buffer.go index 834c0271..144ccafc 100644 --- a/internal/buffer/buffer.go +++ b/internal/buffer/buffer.go @@ -1280,7 +1280,7 @@ func (b *Buffer) Write(bytes []byte) (n int, err error) { return len(bytes), nil } -func (b *Buffer) updateDiffSync() { +func (b *Buffer) updateDiff(synchronous bool) { b.diffLock.Lock() defer b.diffLock.Unlock() @@ -1291,7 +1291,16 @@ func (b *Buffer) updateDiffSync() { } differ := dmp.New() - baseRunes, bufferRunes, _ := differ.DiffLinesToRunes(string(b.diffBase), string(b.Bytes())) + + if !synchronous { + b.Lock() + } + bytes := b.Bytes() + if !synchronous { + b.Unlock() + } + + baseRunes, bufferRunes, _ := differ.DiffLinesToRunes(string(b.diffBase), string(bytes)) diffs := differ.DiffMainRunes(baseRunes, bufferRunes, false) lineN := 0 @@ -1333,11 +1342,11 @@ func (b *Buffer) UpdateDiff() { } if lineCount < 1000 { - b.updateDiffSync() + b.updateDiff(true) } else if lineCount < 30000 { b.updateDiffTimer = time.AfterFunc(500*time.Millisecond, func() { b.updateDiffTimer = nil - b.updateDiffSync() + b.updateDiff(false) screen.Redraw() }) } else {