From cf101c44b488e9b26b26448f8800d28beed9ca3f Mon Sep 17 00:00:00 2001 From: Zoltan Papp Date: Thu, 2 Jul 2026 12:22:01 +0200 Subject: [PATCH] [relay] Count winning attempt before draining losers The success path in handleResult left settled at 0, so drainLoser waited on a result that was already consumed and blocked forever, leaking a goroutine and the results channel on every successful race. Increment settled before stop() so drainLoser only waits for actual started losers. --- shared/relay/client/fallback_opener.go | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/relay/client/fallback_opener.go b/shared/relay/client/fallback_opener.go index c79b829cc..7543d25a1 100644 --- a/shared/relay/client/fallback_opener.go +++ b/shared/relay/client/fallback_opener.go @@ -107,6 +107,7 @@ func (c *connRace) startOther() { func (c *connRace) handleResult(res raceAttempt) raceOutcome { if (res.err == nil && res.conn != nil) || errors.Is(res.err, ErrConnAlreadyExists) { + c.settled++ c.stop() return raceOutcome{conn: res.conn, err: res.err, done: true} }