Skip to content

Commit fab23c3

Browse files
committed
improve alreadyLimits
1 parent 8ff61b2 commit fab23c3

2 files changed

Lines changed: 44 additions & 0 deletions

File tree

limiter.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,19 @@ func (l *Limiter) Stop() {
3333
// alreadyLimits returns true if cd is already limited by this Limiter.
3434
// This lets us help the user avoiding double-accounting bandwidth.
3535
func (l *Limiter) alreadyLimits(cd ContextDialer) bool {
36+
seen := make(map[*Dialer]struct{})
3637
for {
3738
if d, ok := cd.(*Dialer); ok {
39+
if d == nil {
40+
return false
41+
}
3842
if d.Limiter == l {
3943
return true
4044
}
45+
if _, ok := seen[d]; ok {
46+
return false
47+
}
48+
seen[d] = struct{}{}
4149
cd = d.ContextDialer
4250
} else {
4351
return false

limiter_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"io"
66
"testing"
7+
"time"
78
)
89

910
func TestLimiter_Stop(t *testing.T) {
@@ -62,3 +63,38 @@ func TestLimiter_Stop_flushesCount(t *testing.T) {
6263
t.Fatalf("got %d want %d", got, n)
6364
}
6465
}
66+
67+
func TestLimiter_Wrap_cyclicDialerChain_doesNotHang(t *testing.T) {
68+
l1 := NewLimiter()
69+
defer l1.Stop()
70+
l2 := NewLimiter()
71+
defer l2.Stop()
72+
73+
d := &Dialer{Limiter: l1}
74+
d.ContextDialer = d
75+
76+
done := make(chan ContextDialer, 1)
77+
go func() {
78+
done <- l2.Wrap(d)
79+
}()
80+
81+
select {
82+
case wrapped := <-done:
83+
if wrapped == nil {
84+
t.Fatal("expected wrapped dialer")
85+
}
86+
case <-time.After(500 * time.Millisecond):
87+
t.Fatal("Wrap hung on cyclic dialer chain")
88+
}
89+
}
90+
91+
func TestLimiter_alreadyLimits_typedNilDialer(t *testing.T) {
92+
l := NewLimiter()
93+
defer l.Stop()
94+
95+
var d *Dialer
96+
var cd ContextDialer = d
97+
if l.alreadyLimits(cd) {
98+
t.Fatal("typed nil dialer should not be detected as already limited")
99+
}
100+
}

0 commit comments

Comments
 (0)