首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GoogleWebRTC挂起(冻结)快速本地应用程序(OpenVidu)中的主线程

GoogleWebRTC挂起(冻结)快速本地应用程序(OpenVidu)中的主线程
EN

Stack Overflow用户
提问于 2021-05-21 09:21:36
回答 2查看 664关注 0票数 6

我们有挂起问题(应用程序冻结由于主线程锁)与我们的iOS (快速)本机应用程序与OpenVidu实现(它使用GoogleWebRTC下罩)。所需的具体条件:需要加入至少有8名参与者的现有房间。对6名参与者来说,这种情况发生的次数少了,而且几乎从来没有少于6次。如果参与者一个接一个地加入,那么只有当你和所有其他参与者都在一起时,才会出现这种情况。这表明了问题的并发性。

GoogleWebRTC挂起setRemoteDescription呼叫:

代码语言:javascript
复制
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. 我将OpenVidu信令服务器处理(RPC协议)从主线程移到单独的线程中。这只会导致锁发生在我创建的一个单独的线程中。它现在不阻止UI,而是阻止OV信令。问题依然存在。
  2. 我将锁添加到处理每个信令事件(参与者加入事件、发布视频等)的同步(一个接一个)。这也无济于事(实际上使情况更糟)。
  3. 我没有使用Cocoapods中的GoogleWebRTC v. 1.1.31999,而是下载了最新的GoogleWebRTC源代码,并在发布配置和被纳入我的项目中构建了它们。这无助于解决这个问题。

如有任何建议/意见,将不胜感激。谢谢!

编辑1:

signaling_threadworker_thread都在等待相同类型的锁。在锁的时候,他们没有执行我的任何代码。

我还尝试在GoogleWebRTC的调试构建中运行,在这种情况下不会发生锁,但是所有的操作都要慢得多(这对于调试来说是可以的,但我们不能在生产中使用)。

编辑2:

我试图为offersetLocalDescription回调添加额外的offersetLocalDescription回调,但这并没有改变什么。这个问题仍然可以很好地再现(几乎100%的时间,如果我有8个有流的参与者):

代码语言:javascript
复制
    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)
                }
            })
        }
    }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-05-31 11:11:18

在OpenVidu团队发表评论后,问题得到了解决,在增加已经在房间里的参与者之间增加了100 in的延迟。我认为这更像是一个黑客,而不是一个真正的解决方案,但我可以确认它在测试和生产环境中都有效:

代码语言:javascript
复制
DispatchQueue.global(qos: .background).async {
    for info in dict.values {
        let remoteParticipant = self.newRemoteParticipant(info: info)
        if let streamId = info.streamId {
            remoteParticipant.createOffer(completion: {(sdp) in
                self.receiveVideoFrom(sdp: sdp, remoteParticipant: remoteParticipant, streamId: streamId)
            })
        } else {
            print("No streamId")
        }
        Thread.sleep(forTimeInterval: 0.1)
    }
}
票数 1
EN

Stack Overflow用户

发布于 2021-05-26 03:45:51

WebRTC Obj可以从任何线程调用,但大多数方法调用都传递给WebRTC的内部线程signalling thread

另外,像SetLocalDescriptionObserverInterfaceRTCSetSessionDescriptionCompletionHandler这样的回调/观察者是从signaling thread上的WebRTC调用的。

从屏幕截图来看,信令线程目前似乎已被阻塞,无法再调用WebRTC API调用。

因此,为了避免死锁,最好创建自己的线程/ dispatch_queue并处理回调。

详细信息请参见https://webrtc.googlesource.com/src/+/0a52ede821ba12ee6fff6260d69cddcca5b86a4e/api/g3doc/index.mddesign.md

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67634075

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档