iOS 10.2:在CoreFoundation上了解“互斥锁失败:参数无效”

几周前,iOS 10.2开始推出,Spreaker Podcast Radio几乎立即开始从10.2设备获取流量。

我们始终对崩溃进行严格监控,因此几天后,虽然iOS 10.2市场渗透率不断提高,但我们立即注意到iOS 10.2上平均每日崩溃的趋势有所增加。 这是从实际堆栈跟踪中提取的:

或这个:

如您所见,整个堆栈仅包含平台代码,因此一开始很难理解正在发生什么以及涉及应用程序的哪一部分。 我们还注意到有时涉及一些Javascript内容,wtf? 唯一的线索来自我们的日志:每次崩溃发生时,应用程序所做的最后一件事就是尝试从网络中播放(或预加载)音频文件。

我们的应用程序播放了来自多个不同来源的音频文件,并且在这些崩溃中均未发生这些音频文件,这些数据并未显示出某个音频文件(或远程托管)与这些崩溃之间的任何特定关联,我们也无法找到一种在本地播放它们的方法,只是玩一些随机的东西。

在花了数小时收集更多信息之后,我们偶然发现了Core Foundation参考,其中提到了在与代理自动配置相关的函数中通过CFArray和CFError传递结果的某些信息,并且在我们的堆栈跟踪中,这些对PAC / PACClient / PACFetcher的引用晦涩难懂。

if如果PAC表示“代理自动配置”怎么办? 💡💡💡

我们以前没有使用高级代理配置的经验,只是知道有一种方法可以配置设备以自动发现代理设置。 您可以浏览此站点以了解其详细信息,但为了简短起见,它类似于以下内容:

  1. 您配置代理自动发现设置以从远程URL获取配置
  2. 该URL用PAC文件答复,该文件是公开入口函数的Javascript文件。
  3. 在执行过程中,系统调用此函数,传递要获取的资源的url,该函数需要返回如何获取资源的方式,例如通过使用特定的代理或直接连接。

我们立即尝试运行Charles Proxy,并在请求/proxy.pac启动本地http服务器来提供此PAC文件:

并使用以下网址在iOS设备上配置代理设置:

  http:// : /proxy.pac 

有效!!! 好吧,它崩溃了,但这正是重现问题的关键,对吗?

那么,什么触发了此行为以及如何解决呢? 为了在我们的应用程序中提供出色的播放体验,我们必须实现自己的播放系统,而不是依靠Apple提供的基本AVAudioPlayer,并且此播放系统的某些内部组件直接处理CoreFoundation流。 从HTTP请求创建流后,我们对其进行配置,以考虑系统代理设置,方法是:

显然,注释最后两行将导致崩溃立即停止,但这意味着,如果您的网络仅允许通过代理的出站流量,则播放系统将无法工作。

有99.99%的人确定这是iOS 10.2上的错误,并且受iOS上一些Websocket库中所做工作的启发,其中CoreFoundation不会自动使用代理设置,因为它不了解ws://wss://方案(此处为示例),我们决定手动实现Proxy Auto-Discovery协议, 但仅在iOS 10.2上,这是我们支持的唯一iOS版本(iOS8 +),不能自行处理 。 这项工作涉及:

  1. 查看代理设置,并检查是否启用了自动发现协议
  2. 提取PAC文件,并将其内容与CFNetworkCopyProxiesForAutoConfigurationScript一起使用,以确定需要使用哪个代理
  3. 相应地在流上设置kCFStreamPropertyHTTPProxy属性。

这里有人遇到过这个问题吗? 您是否还有其他想法可以改善此解决方法并使它更好地工作? 在评论中让我知道!

再见!

Interesting Posts