fix(eth): make peer removal idempotent to stop unregister flood - #2527
fix(eth): make peer removal idempotent to stop unregister flood#2527gzliudan wants to merge 1 commit into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
36009a5 to
f8d88e6
Compare
f8d88e6 to
208fbec
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Suppressed comments (4)
eth/handler_test.go:850
- This test only checks the final peer-set size, which was already zero before this change even when every concurrent caller reran the unregister sequence. It therefore does not regress the reported warning flood or verify the new exactly-once side effects. Add instrumentation or log capture that asserts downloader/peer-set unregistration occurs once under synchronized concurrent calls.
pm.removePeer(tp.id)
eth/downloader/downloader_test.go:2326
- The implementation logs this case at Debug level, not as a warning. Update the test documentation so it matches the behavior being locked in.
// logging a warning about the state inconsistency.
eth/peer_test.go:43
peerSet.Registerstarts two broadcaster goroutines, but this peer has a niltermchannel andUnregisterdoes not stop them, so this test leaks both goroutines until the test process exits. Initializetermand close it during cleanup.
p := &peer{id: "twice"}
eth/downloader/downloader.go:369
- This at-most-once requirement contradicts both the implementation and
TestDownloaderUnregisterPeerIdempotent: a repeated call also produceserrNotRegisteredand returns nil, so the function cannot infer that the peer was genuinely never registered. Document the actual idempotent contract instead.
// The caller must guarantee at-most-once semantics per peer. Today only
// ProtocolManager.removePeer calls this, and its markRemoved guard ensures a
// peer is unregistered at most once; as long as that invariant holds, an
// errNotRegistered here means the peer was genuinely never registered rather
// than a benign repeat call. If a second caller is ever added, it must uphold
3dd2271 to
9f5c82b
Compare
Concurrent removePeer callers (BFT broadcast loops, DAO fork timers, normal teardown, and the downloader/fetcher drop callbacks) can all pass the Peer(id) lookup before the first caller unregisters the peer, so each re-runs the unregister sequence and floods the logs with "peer is not registered" warnings on every peer drop. Mark peer removal with an atomic flag so the unregister sequence runs exactly once, and let downloader.UnregisterPeer treat an unregistered peer as a silent no-op. In the same race window, handle() could register a peer in the downloader after its removal was claimed, leaving a stale entry that blocks a reconnect of the same node id; re-check the flag after registering and undo the registration.
9f5c82b to
7508505
Compare
Proposed changes
When a peer disconnects, my node will instantly flash about 150+duplicate alarms::
Concurrent removePeer callers (BFT broadcast loops, DAO fork timers, normal teardown, and the downloader/fetcher drop callbacks) can all pass the Peer(id) lookup before the first caller unregisters the peer, so each re-runs the unregister equence and floods the logs with "peer is not registered" warnings on every peer drop.
Mark peer removal with an atomic flag so the unregister sequence runs exactly once, and let downloader.UnregisterPeer treat an unregistered peer as a silent no-op. In the same race window, handle() could register a peer in the downloader after its removal was claimed, leaving a stale entry that blocks a reconnect of the same node id; re-check the flag after
registering and undo the registration.
Types of changes
What types of changes does your code introduce to XDC network?
Put an
✅in the boxes that applyImpacted Components
Which parts of the codebase does this PR touch?
Put an
✅in the boxes that applyChecklist
Put an
✅in the boxes once you have confirmed below actions (or provide reasons on not doing so) that