Skip to content

Commit 6e032c0

Browse files
author
Ibrahim Jarif
authored
Fix race condition in DoesNotHave (#1287)
There is a race condition in the `t.bf` variable if `table.LoadBloomsOnOpen` is set to `false`. This issue was also seen in hypermodeinc/dgraph#4689 (comment)
1 parent fa94030 commit 6e032c0

File tree

2 files changed

+25
-0
lines changed

2 files changed

+25
-0
lines changed

table/table.go

+5
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ type Table struct {
9696

9797
fd *os.File // Own fd.
9898
tableSize int // Initialized in OpenTable, using fd.Stat().
99+
bfLock sync.Mutex
99100

100101
blockIndex []*pb.BlockOffset
101102
ref int32 // For file garbage collection. Atomic.
@@ -381,7 +382,9 @@ func (t *Table) readIndex() error {
381382
t.blockIndex = index.Offsets
382383

383384
if t.opt.LoadBloomsOnOpen {
385+
t.bfLock.Lock()
384386
t.bf, _ = t.readBloomFilter()
387+
t.bfLock.Unlock()
385388
}
386389

387390
return nil
@@ -511,11 +514,13 @@ func (t *Table) DoesNotHave(hash uint64) bool {
511514

512515
// Return fast if the cache is absent.
513516
if t.opt.BfCache == nil {
517+
t.bfLock.Lock()
514518
// Load bloomfilter into memory if the cache is absent.
515519
if t.bf == nil {
516520
y.AssertTrue(!t.opt.LoadBloomsOnOpen)
517521
t.bf, _ = t.readBloomFilter()
518522
}
523+
t.bfLock.Unlock()
519524
return !t.bf.Has(hash)
520525
}
521526

table/table_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"os"
2626
"sort"
2727
"strings"
28+
"sync"
2829
"testing"
2930
"time"
3031

@@ -932,3 +933,22 @@ func TestOpenKVSize(t *testing.T) {
932933
var entrySize uint64 = 15 /* DiffKey len */ + 4 /* Header Size */ + 4 /* Encoded vp */
933934
require.Equal(t, entrySize, table.EstimatedSize())
934935
}
936+
937+
// Run this test with command "go test -race -run TestDoesNotHaveRace"
938+
func TestDoesNotHaveRace(t *testing.T) {
939+
opts := getTestTableOptions()
940+
f := buildTestTable(t, "key", 10000, opts)
941+
table, err := OpenTable(f, opts)
942+
require.NoError(t, err)
943+
defer table.DecrRef()
944+
945+
var wg sync.WaitGroup
946+
wg.Add(5)
947+
for i := 0; i < 5; i++ {
948+
go func() {
949+
require.True(t, table.DoesNotHave(uint64(1237882)))
950+
wg.Done()
951+
}()
952+
}
953+
wg.Wait()
954+
}

0 commit comments

Comments
 (0)