Skip to content

Commit

Permalink
🩹 Fix: race condition in memory storage
Browse files Browse the repository at this point in the history
This commit updates `Conn` method of memory storage to fix race conditions.

Fixes: gofiber#2400
  • Loading branch information
Hrily committed Oct 8, 2023
1 parent 6ecd607 commit f05dd94
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 7 deletions.
10 changes: 5 additions & 5 deletions internal/storage/memory/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,9 @@ func (s *Storage) gc() {
}
}

// Return database client
func (s *Storage) Conn() map[string]entry {
s.mux.RLock()
defer s.mux.RUnlock()
return s.db
// ConnLocked can be used to access the underlying db in a thread-safe manner.
func (s *Storage) ConnLocked(f func(map[string]entry)) {
s.mux.Lock()
defer s.mux.Unlock()
f(s.db)
}
34 changes: 32 additions & 2 deletions internal/storage/memory/memory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,39 @@ func Test_Storage_Memory_Close(t *testing.T) {
utils.AssertEqual(t, nil, testStore.Close())
}

func Test_Storage_Memory_Conn(t *testing.T) {
func Test_Storage_Memory_ConnLocked(t *testing.T) {
t.Parallel()
utils.AssertEqual(t, true, testStore.Conn() != nil)
assertConn := func(db map[string]entry) {
utils.AssertEqual(t, true, db != nil)
}
testStore.ConnLocked(assertConn)
}

func Test_Storage_Memory_ConnLocked_Race(t *testing.T) {
key := "test_race"
done := make(chan bool)
read := func(db map[string]entry) {
_ = db[key]
}
write := func(db map[string]entry) {
db[key] = entry{}
}
doUntilDone := func(fn func(map[string]entry)) {
for {
select {
case <-done:
return
default:
testStore.ConnLocked(fn)
}
}
}

go doUntilDone(read)
go doUntilDone(write)

time.Sleep(100 * time.Millisecond)
done <- true
}

// go test -v -run=^$ -bench=Benchmark_Storage_Memory -benchmem -count=4
Expand Down

0 comments on commit f05dd94

Please sign in to comment.