mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-07-28 01:27:58 +00:00
fix(evolution): use CompareAndSwap for atomic lockStoreFile repair
Replace the Delete+LoadOrStore pattern with CompareAndSwap to atomically swap in a fresh mutex when a corrupted entry is detected. Changes: - Use a retry loop with CAS instead of Delete+LoadOrStore, avoiding the race where two goroutines could create different mutexes - Add nil check: a nil *sync.Mutex passes the type assertion but panics on Lock() — now handled by the CAS recovery path - Use continue-loop retry instead of unchecked second assertion CompareAndSwap guarantees that when multiple goroutines detect a corrupted entry, they converge on the same replacement mutex.
This commit is contained in:
+13
-12
@@ -554,19 +554,20 @@ func isInvalidJSON(err error) bool {
|
||||
}
|
||||
|
||||
func lockStoreFile(path string) func() {
|
||||
actual, _ := storeFileLocks.LoadOrStore(path, &sync.Mutex{})
|
||||
mu, ok := actual.(*sync.Mutex)
|
||||
if !ok {
|
||||
// Delete the corrupted entry so that the next LoadOrStore
|
||||
// atomically creates a fresh mutex. Multiple goroutines may
|
||||
// race to Delete, but LoadOrStore ensures they all converge
|
||||
// on the same mutex before entering the critical section.
|
||||
storeFileLocks.Delete(path)
|
||||
actual, _ = storeFileLocks.LoadOrStore(path, &sync.Mutex{})
|
||||
mu = actual.(*sync.Mutex)
|
||||
for {
|
||||
actual, _ := storeFileLocks.LoadOrStore(path, &sync.Mutex{})
|
||||
mu, ok := actual.(*sync.Mutex)
|
||||
if !ok || mu == nil {
|
||||
// Corrupted entry (wrong type or nil *sync.Mutex).
|
||||
// Atomically swap in a fresh mutex via CompareAndSwap.
|
||||
// If CAS fails, another goroutine already replaced it —
|
||||
// just retry the loop to pick up the valid entry.
|
||||
storeFileLocks.CompareAndSwap(path, actual, &sync.Mutex{})
|
||||
continue
|
||||
}
|
||||
mu.Lock()
|
||||
return mu.Unlock
|
||||
}
|
||||
mu.Lock()
|
||||
return mu.Unlock
|
||||
}
|
||||
|
||||
func (s *Store) profilePath(workspaceID, skillName string) (string, error) {
|
||||
|
||||
Reference in New Issue
Block a user