Skip to content

Commit 6d189f9

Browse files
committed
fix timeout loop early exit when removing expired matchers
1 parent a563d65 commit 6d189f9

2 files changed

Lines changed: 19 additions & 7 deletions

File tree

p2p/discover/common.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
package discover
1818

1919
import (
20+
"container/list"
2021
"crypto/ecdsa"
2122
crand "crypto/rand"
2223
"encoding/binary"
24+
"iter"
2325
"math/rand"
2426
"net"
2527
"net/netip"
@@ -143,3 +145,16 @@ func (r *reseedingRandom) Shuffle(n int, swap func(i, j int)) {
143145
defer r.mu.Unlock()
144146
r.cur.Shuffle(n, swap)
145147
}
148+
149+
// iterList iterates over the elements of the given list.
150+
func iterList[T any](l *list.List) iter.Seq2[T, *list.Element] {
151+
return func(yield func(T, *list.Element) bool) {
152+
for el := l.Front(); el != nil; {
153+
next := el.Next()
154+
if !yield(el.Value.(T), el) {
155+
return
156+
}
157+
el = next
158+
}
159+
}
160+
}

p2p/discover/v4_udp.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -446,9 +446,8 @@ func (t *UDPv4) loop() {
446446
}
447447
// Start the timer so it fires when the next pending reply has expired.
448448
now := time.Now()
449-
for el := plist.Front(); el != nil; el = el.Next() {
450-
nextTimeout = el.Value.(*replyMatcher)
451-
if dist := nextTimeout.deadline.Sub(now); dist < 2*respTimeout {
449+
for p, el := range iterList[*replyMatcher](plist) {
450+
if dist := p.deadline.Sub(now); dist < 2*respTimeout {
452451
timeout.Reset(dist)
453452
return
454453
}
@@ -478,8 +477,7 @@ func (t *UDPv4) loop() {
478477

479478
case r := <-t.gotreply:
480479
var matched bool // whether any replyMatcher considered the reply acceptable.
481-
for el := plist.Front(); el != nil; el = el.Next() {
482-
p := el.Value.(*replyMatcher)
480+
for p, el := range iterList[*replyMatcher](plist) {
483481
if p.from == r.from && p.ptype == r.data.Kind() && p.ip == r.ip {
484482
ok, requestDone := p.callback(r.data)
485483
matched = matched || ok
@@ -499,8 +497,7 @@ func (t *UDPv4) loop() {
499497
nextTimeout = nil
500498

501499
// Notify and remove callbacks whose deadline is in the past.
502-
for el := plist.Front(); el != nil; el = el.Next() {
503-
p := el.Value.(*replyMatcher)
500+
for p, el := range iterList[*replyMatcher](plist) {
504501
if now.After(p.deadline) || now.Equal(p.deadline) {
505502
p.errc <- errTimeout
506503
plist.Remove(el)

0 commit comments

Comments
 (0)