@@ -63,7 +63,11 @@ type ServerPoolTest struct {
6363 trusted []string
6464 waitCount , waitEnded int32
6565
66- lock sync.Mutex
66+ // preNegLock protects the cycle counter, testNodes list and its connected field
67+ // (accessed from both the main thread and the preNeg callback)
68+ preNegLock sync.Mutex
69+ queryWg * sync.WaitGroup // a new wait group is created each time the simulation is started
70+ stopping bool // stopping avoid callind queryWg.Add after queryWg.Wait
6771
6872 cycle , conn , servedConn int
6973 serviceCycles , dialCount int
@@ -111,13 +115,21 @@ func (s *ServerPoolTest) addTrusted(i int) {
111115
112116func (s * ServerPoolTest ) start () {
113117 var testQuery QueryFunc
118+ s .queryWg = new (sync.WaitGroup )
114119 if s .preNeg {
115120 testQuery = func (node * enode.Node ) int {
121+ s .preNegLock .Lock ()
122+ if s .stopping {
123+ s .preNegLock .Unlock ()
124+ return 0
125+ }
126+ s .queryWg .Add (1 )
116127 idx := testNodeIndex (node .ID ())
117128 n := & s .testNodes [idx ]
118- s .lock .Lock ()
119129 canConnect := ! n .connected && n .connectCycles != 0 && s .cycle >= n .nextConnCycle
120- s .lock .Unlock ()
130+ s .preNegLock .Unlock ()
131+ defer s .queryWg .Done ()
132+
121133 if s .preNegFail {
122134 // simulate a scenario where UDP queries never work
123135 s .beginWait ()
@@ -181,11 +193,20 @@ func (s *ServerPoolTest) start() {
181193}
182194
183195func (s * ServerPoolTest ) stop () {
196+ // disable further queries and wait if one is currently running
197+ s .preNegLock .Lock ()
198+ s .stopping = true
199+ s .preNegLock .Unlock ()
200+ s .queryWg .Wait ()
201+
184202 quit := make (chan struct {})
185203 s .quit <- quit
186204 <- quit
187205 s .sp .Stop ()
188206 s .spi .Close ()
207+ s .preNegLock .Lock ()
208+ s .stopping = false
209+ s .preNegLock .Unlock ()
189210 for i := range s .testNodes {
190211 n := & s .testNodes [i ]
191212 if n .connected {
@@ -205,7 +226,9 @@ func (s *ServerPoolTest) run() {
205226 n := & s .testNodes [idx ]
206227 s .sp .UnregisterNode (n .node )
207228 n .totalConn += s .cycle
229+ s .preNegLock .Lock ()
208230 n .connected = false
231+ s .preNegLock .Unlock ()
209232 n .node = nil
210233 s .conn --
211234 if n .service {
@@ -230,7 +253,9 @@ func (s *ServerPoolTest) run() {
230253 s .servedConn ++
231254 }
232255 n .totalConn -= s .cycle
256+ s .preNegLock .Lock ()
233257 n .connected = true
258+ s .preNegLock .Unlock ()
234259 dc := s .cycle + n .connectCycles
235260 s .disconnect [dc ] = append (s .disconnect [dc ], idx )
236261 n .node = dial
@@ -242,9 +267,9 @@ func (s *ServerPoolTest) run() {
242267 }
243268 s .serviceCycles += s .servedConn
244269 s .clock .Run (time .Second )
245- s .lock .Lock ()
270+ s .preNegLock .Lock ()
246271 s .cycle ++
247- s .lock .Unlock ()
272+ s .preNegLock .Unlock ()
248273 }
249274}
250275
@@ -255,11 +280,13 @@ func (s *ServerPoolTest) setNodes(count, conn, wait int, service, trusted bool)
255280 idx = rand .Intn (spTestNodes )
256281 }
257282 res = append (res , idx )
283+ s .preNegLock .Lock ()
258284 s .testNodes [idx ] = spTestNode {
259285 connectCycles : conn ,
260286 waitCycles : wait ,
261287 service : service ,
262288 }
289+ s .preNegLock .Unlock ()
263290 if trusted {
264291 s .addTrusted (idx )
265292 }
@@ -273,7 +300,9 @@ func (s *ServerPoolTest) resetNodes() {
273300 n .totalConn += s .cycle
274301 s .sp .UnregisterNode (n .node )
275302 }
303+ s .preNegLock .Lock ()
276304 s .testNodes [i ] = spTestNode {totalConn : n .totalConn }
305+ s .preNegLock .Unlock ()
277306 }
278307 s .conn , s .servedConn = 0 , 0
279308 s .disconnect = make (map [int ][]int )
0 commit comments