Skip to content

Commit dc841ac

Browse files
authored
Merge pull request #5314 from ogulcanaydogan/fix/filestore-lock-failure-unlock
fix(store): release the mutex when the file store lock fails
2 parents b964815 + 1fefb8f commit dc841ac

2 files changed

Lines changed: 33 additions & 0 deletions

File tree

‎pkg/store/filestore.go‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ func (vs *fileStore) Lock() error {
7676

7777
dirFile, err := filesystem.Lock(vs.dir)
7878
if err != nil {
79+
// Release the in-process mutex, otherwise any later Lock call would block forever.
80+
vs.mutex.Unlock()
81+
7982
return errors.Join(ErrLockFailure, err)
8083
}
8184

‎pkg/store/filestore_test.go‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package store
1818

1919
import (
20+
"os"
21+
"path/filepath"
2022
"testing"
2123
"time"
2224

@@ -220,3 +222,31 @@ func TestFileStoreConcurrent(t *testing.T) {
220222
})
221223
assert.NilError(t, lErr, "locking should not error")
222224
}
225+
226+
func TestFileStoreLockFailureReleasesMutex(t *testing.T) {
227+
parentDir := t.TempDir()
228+
storeDir := filepath.Join(parentDir, "store")
229+
230+
tempStore, err := New(storeDir, 0, 0)
231+
assert.NilError(t, err, "temporary store creation should succeed")
232+
233+
// Locking a store whose directory and parent are gone must fail.
234+
assert.NilError(t, os.RemoveAll(parentDir))
235+
err = tempStore.Lock()
236+
assert.ErrorIs(t, err, ErrLockFailure)
237+
238+
// A failed Lock must not leave the store locked: once the directory is back, locking works again.
239+
assert.NilError(t, os.MkdirAll(storeDir, defaultDirPerm))
240+
241+
done := make(chan error, 1)
242+
go func() {
243+
done <- tempStore.WithLock(func() error { return nil })
244+
}()
245+
246+
select {
247+
case err = <-done:
248+
assert.NilError(t, err, "locking after a failed lock should succeed")
249+
case <-time.After(5 * time.Second):
250+
t.Fatal("Lock blocked forever after a previous Lock failure")
251+
}
252+
}

0 commit comments

Comments
 (0)