我们的 iOS (swift) native 应用程序与 OpenVidu 实现(在引擎盖下使用 GoogleWebRTC)存在挂起问题(应用程序由于主线程锁定而卡住)。需要的具体条件:需要加入现有的房间,并且至少有 8 名参与者已经在直播。有 6 名参与者时,这种情况发生的频率较低,而且在 6 人以下时几乎不会发生。如果参与者一个一个加入,它不会挂起,只有当您加入房间时所有其他参与者都已经在流式传输。这表明问题的并发性质。
GoogleWebRTC 挂起 setRemoteDescription
称呼:
func setRemoteDescription(sdpAnswer: String) {
let sessionDescription: RTCSessionDescription = RTCSessionDescription(type: RTCSdpType.answer, sdp: sdpAnswer)
self.peerConnection!.setRemoteDescription(sessionDescription, completionHandler: {(error) in
print("Local Peer Remote Description set: " + error.debugDescription)
})
}
正如你在上面的截图中看到的,主线程卡在
__psynch_cvwait
上。 .似乎没有任何其他线程被锁定。 锁永远不会释放 让应用程序完全卡住。为了解决这个问题,我尝试了以下方法:
任何建议/意见将不胜感激。
谢谢!
编辑 1:
signaling_thread
和 worker_thread
两者都在等待同一种锁中的东西。在锁定的那一刻,他们都没有执行我的任何代码。我还尝试在
GoogleWebRTC
的调试版本中运行,在这种情况下不会发生锁定,但一切都运行得更慢(这对于调试来说是可以的,但我们不能在生产中使用它)。编辑 2:
我试图添加额外的
DispatchQueue
为 offer
和 setLocalDescription
回调,但这没有任何改变。该问题仍然可以很好地重现(几乎 100% 的时间,如果我有 8 个参与者有流): self.peerConnection!.offer(for: constrains) { (sdp, error) in
DispatchQueue.global(qos: .background).async {
guard let sdp = sdp else {
return
}
self.peerConnection!.setLocalDescription(sdp, completionHandler: { (error) in
DispatchQueue.global(qos: .background).async {
completion(sdp)
}
})
}
}
最佳答案
WebRTC Obj-C API 可以从任何线程调用,但大多数方法调用被传递到 WebRTC 的内部线程,称为 signalling thread
.
此外,回调/观察者如 SetLocalDescriptionObserverInterface
或 RTCSetSessionDescriptionCompletionHandler
在 signaling thread
上从 WebRTC 调用.
看截图,好像是信令线程当前被阻塞了,不能再调用WebRTC API调用了。
因此,为了避免死锁,最好创建自己的线程/dispatch_queue
并处理回调。
看
https://webrtc.googlesource.com/src/+/0a52ede821ba12ee6fff6260d69cddcca5b86a4e/api/g3doc/index.md和
https://webrtc.googlesource.com/src/+/0a52ede821ba12ee6fff6260d69cddcca5b86a4e/api/g3doc/threading_design.md
详情。
关于swift - GoogleWebRTC 挂起(卡住)swift native 应用程序(OpenVidu)中的主线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67634075/