From a37824d1f85af9610f37d51692f22ea5b7ed3f19 Mon Sep 17 00:00:00 2001 From: Tanvir Date: Fri, 17 Apr 2026 03:23:22 +0800 Subject: [PATCH] p2p/discover: fix timeout loop early exit when removing expired matchers Save `el.Next()` before calling `plist.Remove(el)` so iteration continues correctly. Previously the loop exited after removing the first expired matcher because `Remove` invalidates the element's links. --- p2p/discover/v4_udp.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/p2p/discover/v4_udp.go b/p2p/discover/v4_udp.go index dd3f363f7e..8702aa5d3f 100644 --- a/p2p/discover/v4_udp.go +++ b/p2p/discover/v4_udp.go @@ -499,13 +499,15 @@ func (t *UDPv4) loop() { nextTimeout = nil // Notify and remove callbacks whose deadline is in the past. - for el := plist.Front(); el != nil; el = el.Next() { + for el := plist.Front(); el != nil; { + next := el.Next() p := el.Value.(*replyMatcher) if now.After(p.deadline) || now.Equal(p.deadline) { p.errc <- errTimeout plist.Remove(el) contTimeouts++ } + el = next } // If we've accumulated too many timeouts, do an NTP time sync check if contTimeouts > ntpFailureThreshold {