@@ -232,10 +232,11 @@ type urlTestGroup struct {
232232 selectedOutboundTCP atomic.TypedValue [A.Outbound ]
233233 selectedOutboundUDP atomic.TypedValue [A.Outbound ]
234234 access sync.Mutex
235+ running atomic.Bool
235236 ticker * time.Ticker
236237 idleTimer * time.Timer
237238 lastActive atomic.TypedValue [time.Time ]
238- close chan struct {}
239+ stop chan struct {}
239240 started bool
240241}
241242
@@ -257,7 +258,7 @@ func (g *urlTestGroup) Start() error {
257258 g .history = urltest .NewHistoryStorage ()
258259 }
259260 g .pauseMgr = service.FromContext [pause.Manager ](g .ctx )
260- g .close = make (chan struct {})
261+ g .stop = make (chan struct {})
261262 return nil
262263}
263264
@@ -272,18 +273,19 @@ func (g *urlTestGroup) PostStart() {
272273func (g * urlTestGroup ) Close () error {
273274 g .access .Lock ()
274275 defer g .access .Unlock ()
275- if g .ticker == nil {
276+ if g .isClosed () {
276277 return nil
277278 }
278279 g .ticker .Stop ()
280+ g .idleTimer .Stop ()
279281 g .pauseMgr .UnregisterCallback (g .pauseCallback )
280- close (g .close )
282+ close (g .stop )
281283 return nil
282284}
283285
284286func (g * urlTestGroup ) isClosed () bool {
285287 select {
286- case <- g .close :
288+ case <- g .stop :
287289 return true
288290 default :
289291 return false
@@ -336,7 +338,7 @@ func (g *urlTestGroup) Remove(tags []string) (n int, err error) {
336338 g .tags = append (g .tags , tag )
337339 }
338340 if len (g .tags ) == 0 {
339- g .pauseCheckLoop ()
341+ g .stop <- struct {}{}
340342 g .selectedOutboundTCP .Store (nil )
341343 g .selectedOutboundUDP .Store (nil )
342344 }
@@ -350,7 +352,7 @@ func (g *urlTestGroup) keepAlive() {
350352 if ! g .started {
351353 return
352354 }
353- if g . ticker != nil {
355+ if ! g . running . CompareAndSwap ( false , true ) {
354356 g .lastActive .Store (time .Now ())
355357 g .idleTimer .Reset (g .idleTimeout )
356358 return
@@ -366,24 +368,20 @@ func (g *urlTestGroup) checkLoop() {
366368 g .CheckOutbounds (false )
367369 }
368370 g .idleTimer = time .NewTimer (g .idleTimeout )
371+ loop:
369372 for {
370373 select {
371- case <- g .close :
372- return
374+ case <- g .stop :
375+ break loop
373376 case <- g .ticker .C :
374377 g .CheckOutbounds (false )
375378 case <- g .idleTimer .C :
376- g .pauseCheckLoop ()
377- return
379+ break loop
378380 }
379381 }
380- }
381-
382- func (g * urlTestGroup ) pauseCheckLoop () {
383382 g .access .Lock ()
384383 g .ticker .Stop ()
385- g .ticker = nil
386- g .idleTimer = nil
384+ g .running .Store (false )
387385 g .pauseMgr .UnregisterCallback (g .pauseCallback )
388386 g .pauseCallback = nil
389387 g .access .Unlock ()
0 commit comments