From 7aa7806c0958ed943965e8180fdeeecea8171516 Mon Sep 17 00:00:00 2001 From: ozpool <151670776+ozpool@users.noreply.github.com> Date: Thu, 2 Jul 2026 21:50:25 +0530 Subject: [PATCH] cmd/devp2p: close the iterator in discv4 LookupRandom (#35206) The LookupRandom RPC handler obtains a node iterator from RandomNodes() but never closes it. RandomNodes() returns a lookupIterator backed by a cancelable context derived from the listener's lifetime context (newLookupIterator -> context.WithCancel). The iterator's Close() is what calls the cancel func, so each LookupRandom call that never closes leaks the cancel func (and any in-flight lookup goroutine) until the discv4 listener shuts down. When the listener serves the RPC API (discv4 --rpc) it is long-lived, so repeated LookupRandom calls accumulate the leak. Close the iterator when the handler returns. This matches how the crawler already releases the same RandomNodes() iterators (crawl.go closes every iterator it consumes). --- cmd/devp2p/discv4cmd.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/devp2p/discv4cmd.go b/cmd/devp2p/discv4cmd.go index 1089210c57..98b04311b4 100644 --- a/cmd/devp2p/discv4cmd.go +++ b/cmd/devp2p/discv4cmd.go @@ -430,6 +430,7 @@ type discv4API struct { func (api *discv4API) LookupRandom(n int) (ns []*enode.Node) { it := api.host.RandomNodes() + defer it.Close() for len(ns) < n && it.Next() { ns = append(ns, it.Node()) }