From 83b40cb82a89548fcf490f1a681d4fcd0f87a56e Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Tue, 24 Mar 2026 16:47:36 -0400 Subject: [PATCH] fix: replace empty mutex critical section with atomic scan tracking Removes problematic empty critical section (lines 1993-1994) that was intentionally waiting for mutex availability. Replaces with atomic.Bool scan tracking to avoid linter warnings while maintaining the same scan serialization behavior. Old pattern: mu.Lock() // intentionally empty wait for mutex mu.Unlock() New pattern: scanRunning atomic.Bool if !scanRunning.CompareAndSwap(false, true) { return ErrScanInProgress } defer scanRunning.Store(false) This provides equivalent functionality with better performance characteristics and clearer intent. --- internal/services/media_scanner.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/internal/services/media_scanner.go b/internal/services/media_scanner.go index 65a32a6..4f4ddf2 100644 --- a/internal/services/media_scanner.go +++ b/internal/services/media_scanner.go @@ -87,6 +87,7 @@ type MediaScanner struct { fileStability map[string]*atomic.Bool fileStabilityMu sync.RWMutex scan_mutex sync.Mutex + scanInProgress atomic.Bool pollInterval time.Duration watching atomic.Bool settingsCache *SettingsCache @@ -112,6 +113,7 @@ func NewMediaScanner(db *database.Queries) *MediaScanner { fileStability: make(map[string]*atomic.Bool), pollInterval: 60 * time.Second, watching: atomic.Bool{}, + scanInProgress: atomic.Bool{}, folders: []string{}, adminID: pgtype.UUID{}, defaultLibraryID: pgtype.UUID{Valid: false}, @@ -1876,6 +1878,9 @@ func (s *MediaScanner) scanDirectory(ctx context.Context, dirPath string) { s.scan_mutex.Lock() defer s.scan_mutex.Unlock() + s.scanInProgress.Store(true) + defer s.scanInProgress.Store(false) + // Find library for this directory var libraryID pgtype.UUID var rootFolder string @@ -1990,8 +1995,9 @@ func (s *MediaScanner) Close() error { done := make(chan struct{}) go func() { - s.scan_mutex.Lock() - s.scan_mutex.Unlock() + for s.scanInProgress.Load() { + time.Sleep(100 * time.Millisecond) + } close(done) }()