From a324610b8b447d8832ee58befe821eb159fc5fb0 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Tue, 9 Jun 2026 00:24:44 -0700 Subject: [PATCH] fix(ec): take ecjFileAccessLock before the nil-check in Sync and Close Sync and Close read ev.ecjFile before acquiring ecjFileAccessLock while Close nils it under the lock, a data race on the field. Take the lock first, then nil-check inside, in both. --- weed/storage/erasure_coding/ec_volume.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/weed/storage/erasure_coding/ec_volume.go b/weed/storage/erasure_coding/ec_volume.go index 999f63ad7..7ea3373fb 100644 --- a/weed/storage/erasure_coding/ec_volume.go +++ b/weed/storage/erasure_coding/ec_volume.go @@ -232,12 +232,12 @@ func (ev *EcVolume) Close() { for _, s := range ev.Shards { s.Close() } + ev.ecjFileAccessLock.Lock() if ev.ecjFile != nil { - ev.ecjFileAccessLock.Lock() _ = ev.ecjFile.Close() ev.ecjFile = nil - ev.ecjFileAccessLock.Unlock() } + ev.ecjFileAccessLock.Unlock() if ev.ecxFile != nil { _ = ev.ecxFile.Sync() // Do NOT nil ecxFile: LocateEcShardNeedle reads it without the @@ -252,13 +252,13 @@ func (ev *EcVolume) Close() { // This ensures that deletions made via DeleteNeedleFromEcx are visible // to other processes/file handles that may read these files. func (ev *EcVolume) Sync() { + ev.ecjFileAccessLock.Lock() if ev.ecjFile != nil { - ev.ecjFileAccessLock.Lock() if err := ev.ecjFile.Sync(); err != nil { glog.Warningf("failed to sync ecj file for volume %d: %v", ev.VolumeId, err) } - ev.ecjFileAccessLock.Unlock() } + ev.ecjFileAccessLock.Unlock() if ev.ecxFile != nil { if err := ev.ecxFile.Sync(); err != nil { glog.Warningf("failed to sync ecx file for volume %d: %v", ev.VolumeId, err)