记一个SceneKit Morpher引发的Crash

记一个SceneKit Morpher引发的Crash

tags: AR&3D SceneKit

背景

Animoji外网遇到一些Crash, 量不算大但一直存在,由于测试很难复现,只能靠看Log归纳用户的操作路径,对可疑点进行排查。

分析

猜测

外网Crash的堆栈顶都是C3DGeometryGetMesh,进入C3DGeometryGetMesh大多是C3DMorpherUpdateIfNeed或者C3DMorpher的其他方法,但是再往后看调用者,就特别随机了……有时是在更新贴图,有时是在更新表情,甚至是挂在渲染时钟里,没有任何业务代码。
C3D开头的类多是SceneKit、SpriteKit或ModelI/O的底层实现, 从类名结合具体业务逻辑,可以断定和SCNMorpher有关。
Animoji是使用SCNMorpher做表情动画的,当用户选择不同Animoji模型,我会根据优先级加载不同表情,从这里入手开始查起。

Animoji

定位原因

首先我先取消了分批加载表情的策略,在创建模型时就完成加载完表情再去渲染,结果灰度用户还是Crash……
之后分析了业务逻辑和Log, 觉得有可能SCNMohpher不是线程安全的,因为Morpher的创建是异步的。
猜测苹果的实现是异步加载具体网格的顶点数据到自己的Targets的数组,在更新时使用Metal计算每个顶点的变形后位置。

尝试复现

基于上面的分析,首先写了一个时钟,30帧调用选择不同Animoji的接口,果然Crash了,栈的结构与外网的类似。


Crash Stack
现场
现场2

再次分析

从Crash现场和寄存器的来看,Morpher要加载某一个网格时,这个网格的数据是空的,所以Crash了,佐证了我之前的判断。但是如果Morpher这么不安全,那么这个Bug早就应该大面积爆发了,而且Morpher的接口设计也没有加载完成的回调。
在Radar bug给苹果后,继续分析这个Bug的成因,毕竟项目还是要上线的。
分析业务代码,发现Animoji在更换模型时,是重复利用一个Node来操作,更换时只是替换这个Node的Geometry和Morpher等,再控制Node旋转移动等。
由于Morpher是附在Node上的,猜测苹果的实现,Node上可能有Morpher的信息,再一次做实验,用时钟30帧一次更换模型,这一次更换时会重新创建Node,将旧的Node从渲染场景中剥离,并在更新表情时判断Morpher的Targets数量是不是合预期。

// MARK: - code doesn't crash
// Change Animoji
[self.fakerFace removeFromParentNode];
SCNNode *node = [SCNNode node];
SCNMorpher *morpher = [SCNMorpher new];
morpher.calculationMode = SCNMorpherCalculationModeNormalized;
morpher.targets = arr;
morpher.unifiesNormals = YES;
return morpher;
node.morpher = morpher;
self.fakerFace = node;
[self.headParentNode addChildNode:self.fakerFace];
//MARK: - In Render Loop
if (self.fakerFace.morpher.targets > ANIMOJI_BLENDS_COUNT){
    // Update Animoji
}

实验结果表明不会Crash了,就算以60调用也没有问题。

解决

修改代码后,外网已经没有这个Crash了,修复这个Bug主要靠猜苹果的实现……
也给大家分享下这个坑,使用Morpher要注意它的异步创建特点,同时要更换Morpher时要换个Node去持有它,不要直接加载到正在渲染循环中的Node,同时要判断Targets是否符合预期。不然底层代码会在取网格数据是碰到空值,造成Crash.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容