Skip to content

Commit

Permalink
Merge pull request #301 from redis/fix-lock-try-with-context
Browse files Browse the repository at this point in the history
fix: hanging in the cancel fn of rueidislock.TryWithContext
  • Loading branch information
rueian committed Jul 12, 2023
2 parents 862f730 + 4816b0e commit b10717d
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 1 deletion.
2 changes: 1 addition & 1 deletion rueidislock/lock.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ func (m *locker) waitgate(ctx context.Context, name string) (g *gate, err error)

func (m *locker) trygate(name string) (g *gate) {
m.mu.Lock()
g, ok := m.gates[name]
_, ok := m.gates[name]
if !ok {
g = makegate(m.totalcnt)
g.w++
Expand Down
58 changes: 58 additions & 0 deletions rueidislock/lock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,64 @@ func TestLocker_TryWithContext(t *testing.T) {
}
}

func TestLocker_TryWithContext_MultipleLocker(t *testing.T) {
test := func(t *testing.T, noLoop, setpx, nocsc bool) {
lockers := make([]*locker, 10)
sum := make([]int, len(lockers))
for i := 0; i < len(lockers); i++ {
lockers[i] = newLocker(t, noLoop, setpx, nocsc)
lockers[i].timeout = time.Second
}
defer func() {
for _, locker := range lockers {
locker.Close()
}
}()
cnt := 1000
lck := strconv.Itoa(rand.Int())
ctx := context.Background()
var wg sync.WaitGroup
wg.Add(len(lockers))
for i, l := range lockers {
go func(i int, l *locker) {
defer wg.Done()
for j := 0; j < cnt; j++ {
for {
_, cancel, err := l.TryWithContext(ctx, lck)
if err != nil && err != ErrNotLocked {
t.Error(err)
return
}
if cancel != nil {
cancel()
sum[i]++
break
}
time.Sleep(time.Millisecond)
}
}
}(i, l)
}
wg.Wait()
for i, s := range sum {
if s != cnt {
t.Fatalf("unexpected sum %v %v %v", i, s, cnt)
}
}
}
for _, nocsc := range []bool{false, true} {
t.Run("Tracking Loop", func(t *testing.T) {
test(t, false, false, nocsc)
})
t.Run("Tracking NoLoop", func(t *testing.T) {
test(t, true, false, nocsc)
})
t.Run("SET PX", func(t *testing.T) {
test(t, true, true, nocsc)
})
}
}

func TestLocker_WithContext_Cleanup(t *testing.T) {
test := func(t *testing.T, noLoop, setpx, nocsc bool) {
locker := newLocker(t, noLoop, setpx, nocsc)
Expand Down

0 comments on commit b10717d

Please sign in to comment.