Blocked goro if peer connection is closed before ICE candidate gathering completes when using non-trickling ICE #2507
Description
Your environment.
- Version:
v3.2.8
- Browser: N/A
- Other Information - stacktraces, related issues, suggestions how to fix, links for us to have context
What did you do?
We have client that is unable to use trickling ICE, so we use the gathering promise approach to wait until local candidates have been collected before sending the SDP answer:
// Create channel that is blocked until ICE Gathering is complete
gatherComplete := webrtc.GatheringCompletePromise(peerConnection)
answer, err := peerConnection.CreateAnswer(nil)
if err != nil {
panic(err)
} else if err = peerConnection.SetLocalDescription(answer); err != nil {
panic(err)
}
// Block until ICE Gathering is complete, disabling trickle ICE
// we do this because we only can exchange one signaling message
// in a production application you should exchange ICE Candidates via OnICECandidate
<-gatherComplete
We have noticed an occasional networking issue that cause ICE candidate gathering to stall, which after a timeout causes the peer connection to time out. This then closes the ICE agent whilst, due to longer TCP timeouts, the ICE gathering continues. Eventually, the ICE gathering concludes but the GatheringStateComplete
status is never set:
ice WARNING: 2023/06/28 10:30:28 Failed to set gatheringState to GatheringStateComplete: the agent is closed
This results in the gatherComplete
channel never receiving the 'done' signal, which blocks the goro it is running in indefinitely.
This behaviour can be reproduced using the ice-tcp
example with the following diff:
@@ -71,0 +74 @@ func doSignaling(w http.ResponseWriter, r *http.Request) {
+ peerConnection.Close()
<-gatherComplete
What did you expect?
The promise resolves successfully on the peer connection / ICE agent being closed.
What happened?
The peer connection is closed, which closes the ICE agent, but then setting GatheringStateComplete
fails due to the ICE agent being closed. This results in the gathering promise never resolving, which blocks the goro it's running in indefinitely.
Whilst the WebRTC spec may be moving towards trickling ICE as standard, clients are still allowed to be non-trickling and some examples in this repo utilise the gathering promise, so this seems like a pertinent bug to flag.