diff --git a/pkg/analyze/stored.go b/pkg/analyze/stored.go index 7944193..9fc7848 100644 --- a/pkg/analyze/stored.go +++ b/pkg/analyze/stored.go @@ -352,27 +352,45 @@ func (f *StoredDir) updateStats(linkedItems fs.HardLinkedItems, filteringFiles b var itemCount int64 f.cachedFiles = nil files := f.loadFiles() + + // Snapshot the mutable stat fields under the read lock and commit them back + // under the write lock, mirroring Dir.updateStats. Readers of these fields + // (GetSize, GetUsage, GetFlag, GetMtime, GetItemCount) all take f.m, so the + // writes here must take it too, e.g. when the stats are recomputed while a + // preview reads the same directory mid-scan. + f.m.RLock() + mtime := f.Mtime + flag := f.Flag + f.m.RUnlock() + for _, entry := range files { count, size, usage := entry.GetItemStats(linkedItems, filteringFiles) totalSize += size totalUsage += usage itemCount += count - if entry.GetMtime().After(f.Mtime) { - f.Mtime = entry.GetMtime() + entryMtime := entry.GetMtime() + if entryMtime.After(mtime) { + mtime = entryMtime } switch entry.GetFlag() { case '!', '.': - if f.Flag != '!' { - f.Flag = '.' + if flag != '!' { + flag = '.' } } } f.cachedFiles = nil + + f.m.Lock() + f.Mtime = mtime + f.Flag = flag f.ItemCount = itemCount + 1 f.Size = totalSize f.Usage = totalUsage + f.m.Unlock() + err := DefaultStorage.StoreDir(f) if err != nil { log.Print(err.Error())