Repository navigation
fix(p2p/simulations): serialize node info reads with node startup - #2827
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
|
554c5c8 to
90ddff5
Compare
de5f14a to
300bf5e
Compare
|
Disposition of the two open review items: both are won't-fix. No code change follows. 1. NodeInfo's blocking 2. Moving the The comment fix requested in the previous round landed in 300bf5e. |
96a4840 to
d0dacc7
Compare
|
Follow-up on the third review item: the Why: every mutation of the p2p server's protocol list and listen address happens inside Verified empirically on this exact head: a probe hammering Net: all three review items are closed (two wont-fix with reasons above, one retracted), the branch is unchanged, and it is good to merge from my side. |
SimNode.Start registers the services before the devp2p node is started, and node.RegisterProtocols appends to the p2p server's protocol slice in that window. The simulations HTTP API marshals the node info from another goroutine: the event stream does it as soon as a control event is handed over, and the node handlers do it on request. Neither side takes a lock, so a node that is created and then started races with the HTTP layer reading the protocol slice. The new race job in XinFinOrg#2797 reported it as TestHTTPSnapshot failing on p2p.Server.NodeInfo reading srv.Protocols against node.RegisterProtocols appending to it. Hold the startup lock for the whole of Start and take it shared in NodeInfo. The lock order stays startMu -> node.lock, the only other lock in the path, and nothing reached from Start calls NodeInfo, so readers wait for the startup instead of observing a half-filled server. The change is confined to the in-memory adapter and leaves the event and node response payloads alone. Upstream geth deleted p2p/simulations in ethereum#30250 without fixing this, and both NodeInfo and RegisterProtocols are still unsynchronised there, so there is nothing to port. Tests: 100 runs of TestHTTPSnapshot as four concurrent processes under -race (short, count=25 each) report no race; dropping the read lock again makes 3 of the 4 processes fail, so the lock is what keeps it quiet. make all, go test ./p2p/simulations/... pass, golangci-lint 2.12.2 on ./p2p/simulations/... reports no new findings, and make tidy reports no untidy module files.
d0dacc7 to
f5de05c
Compare
Summary
SimNode.Startregisters the services — and therefore appends to the p2p server's protocol slice — before the devp2p node is started. The simulations HTTP API marshals node info from other goroutines (the event stream as soon as a control event is handed over, the node handlers on request) without any synchronisation, so a node that is being started races with readers ofp2p.Server.Protocols.The new race job in #2797 exposed it as
p2p/simulationsfailing onTestHTTPSnapshot:Change
SimNodegainsstartMu, held for the whole ofStartand taken shared inNodeInfo.startMu -> node.lock(the only other lock on the path), and nothing reached fromStartcallsNodeInfo, so there is no cycle.Verification
TestHTTPSnapshotas four concurrentgo test -race -short -count=25processes: no race. The same command on the parent commit failed in 1–2 of the 4 processes.make all,go test ./p2p/simulations/..., golangci-lint 2.12.2 on./p2p/simulations/...(no new findings) andmake tidy(no untidy module files) pass.Upstream
geth removed
p2p/simulationsin ethereum#30250 without fixing this, and bothNodeInfoandRegisterProtocolsare still unsynchronised there, so there is nothing to port.Ref: #2797