From 762059996132f46c81472a2d4b9041deb8e32c23 Mon Sep 17 00:00:00 2001 From: Zoltan Papp Date: Sat, 11 Jul 2026 13:37:59 +0200 Subject: [PATCH] [client] Fix ICE dialer cancel race in WorkerICE.connect The connect goroutine read the agentDialerCancel field without holding muxAgent, racing with OnNewOffer replacing it for a new session. On failure paths the stale read could cancel the new session's dialer instead of its own. Pass the cancel func of the owning session as a parameter, like the dialer context. --- client/internal/peer/worker_ice.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/internal/peer/worker_ice.go b/client/internal/peer/worker_ice.go index b1aa3e0f9..c49a295f7 100644 --- a/client/internal/peer/worker_ice.go +++ b/client/internal/peer/worker_ice.go @@ -151,7 +151,7 @@ func (w *WorkerICE) OnNewOffer(remoteOfferAnswer *OfferAnswer) { w.remoteSessionID = "" } - go w.connect(dialerCtx, agent, remoteOfferAnswer) + go w.connect(dialerCtx, dialerCancel, agent, remoteOfferAnswer) } // OnRemoteCandidate Handles ICE connection Candidate provided by the remote peer. @@ -247,11 +247,11 @@ func (w *WorkerICE) SessionID() ICESessionID { // will block until connection succeeded // but it won't release if ICE Agent went into Disconnected or Failed state, // so we have to cancel it with the provided context once agent detected a broken connection -func (w *WorkerICE) connect(ctx context.Context, agent *icemaker.ThreadSafeAgent, remoteOfferAnswer *OfferAnswer) { +func (w *WorkerICE) connect(ctx context.Context, dialerCancel context.CancelFunc, agent *icemaker.ThreadSafeAgent, remoteOfferAnswer *OfferAnswer) { w.log.Debugf("gather candidates") if err := agent.GatherCandidates(); err != nil { w.log.Warnf("failed to gather candidates: %s", err) - w.closeAgent(agent, w.agentDialerCancel) + w.closeAgent(agent, dialerCancel) return } @@ -259,19 +259,19 @@ func (w *WorkerICE) connect(ctx context.Context, agent *icemaker.ThreadSafeAgent remoteConn, err := w.turnAgentDial(ctx, agent, remoteOfferAnswer) if err != nil { w.log.Debugf("failed to dial the remote peer: %s", err) - w.closeAgent(agent, w.agentDialerCancel) + w.closeAgent(agent, dialerCancel) return } w.log.Debugf("agent dial succeeded") pair, err := agent.GetSelectedCandidatePair() if err != nil { - w.closeAgent(agent, w.agentDialerCancel) + w.closeAgent(agent, dialerCancel) return } if pair == nil { w.log.Warnf("selected candidate pair is nil, cannot proceed") - w.closeAgent(agent, w.agentDialerCancel) + w.closeAgent(agent, dialerCancel) return }