p2p: fix discovery shutdown (#8725) (#8735)

Problem:
Some goroutines are blocked on shutdown:
1. table close <-tab.closed // because table loop pending
1. table loop <-refreshDone // because lookup shutdown blocks doRefresh
1. lookup shutdown <-it.replyCh // because it.queryfunc (findnode -
ensureBond) is blocked, and not returning errClosed (if it returns and
pushes to it.replyCh, then shutdown() will unblock)
1. findnode - ensureBond <-rm.errc // because the related replyMatcher
was added after loop() exited, so there's nothing to push errClosed and
unlock it

If addReplyMatcher channel is buffered, it is possible that
UDPv4.pending() adds a new reply matcher after closeCtx.Done().
Such reply matcher's errc result channel will never be updated, because
the UDPv4.loop() has exited at this point. Subsequent discovery
operations will deadlock.

Solution:
Revert to an unbuffered channel.
This commit is contained in:
battlmonstr 2023-11-17 03:13:44 +01:00 committed by GitHub
parent 1b14921a9d
commit 3ca7fdf7e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -160,7 +160,7 @@ func ListenV4(ctx context.Context, protocol string, c UDPConn, ln *enode.LocalNo
localNode: ln,
db: ln.Database(),
gotreply: make(chan reply, 10),
addReplyMatcher: make(chan *replyMatcher, 10),
addReplyMatcher: make(chan *replyMatcher),
gotkey: make(chan v4wire.Pubkey, 10),
gotnodes: make(chan nodes, 10),
replyTimeout: cfg.ReplyTimeout,