关于3.8中resolveAfterPromiseResolved和rejectAfterPromiseResolved错误

我刚 review 了一下逻辑,在 SimpleLoop 里面加行不通,SimpleRunLoop 应该永远不会被执行的。

由于 2.x 与 3.x 平台抽象层的差异,目前你最简单的改法应该是直接在 EventDispatcher::dispatchTickEvent 的最后,加上你新加的 handlePromiseExceptions()

或者你搜索代码,在所有调用 EventDispatcher::dispatchTickEvent() 之后的逻辑中去触发 handlePromiseExceptions。

收到,我试一下,感谢

我这边改完验证过是ok的,可以给2.4版本提一个mr吗?解决promise相关的问题

可以提一下,不过现在 2.x 发版周期相对比较长。你可以先提交,我们再评估一下在 2.x 哪个版本中去合并。谢谢。

我们在灰度期间的时候,发现会偶现crash,具体的crash信息如下。


想问下为什么同一时间触发了2次EventDispatcher::dispatchTickEvent呢。
@dumganhar

???

2 次 handlePromiseExceptions ?因为这个函数是你自己加到 2.x 引擎中的,你提交一下 PR,我看下具体的改动点。

fix: 修复promise相关错误,issue参考https://forum.cocos.org/t/topic/158288/20 by nai6514531 · Pull Request #4357 · cocos/engine-native · GitHub 这个pr,crash信息是下面这个
0 SIGSEGV:SEGV_ACCERR
1 0 CocosCreator v8::internal::GlobalHandles::NodeSpacev8::internal::GlobalHandles::Node::Release(v8::internal::GlobalHandles::Node*) + 24
2 1 CocosCreator se::ScriptEngine::handlePromiseExceptions() + 128
3 2 CocosCreator se::ScriptEngine::handlePromiseExceptions() + 128
4 3 CocosCreator cocos2d::EventDispatcher::dispatchTickEvent(float) + 244
5 4 CocosCreator -[MainLoop doCaller:] + 240
6 5 QuartzCore CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 832
7 6 QuartzCore display_timer_callback(__CFMachPort*, void*, long, void*) + 368
8 7 CoreFoundation CFMachPortPerform + 172
9 8 CoreFoundation CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION
+ 56
10 9 CoreFoundation _CFRunLoopDoSource1 + 512
11 10 CoreFoundation _CFRunLoopRun + 2332
12 11 CoreFoundation _CFRunLoopRunSpecific + 584
13 12 GraphicsServices _GSEventRunModal + 160

你有没有存项目的 symbol 文件,有的话,可以还原出 handlePromiseExceptions 哪行的问题。

只在线上出现吗?本地模拟一个 promise 错误,能否触发这个问题?

我们灰度数据大概有900个进入游戏的,crash发生一次。本地测试的时候模拟了很多promise的错误,触发不了类似的crash

项目的c++crash问题只能定位到函数,需要自己分析函数的实现。暂时定位不到具体哪一行

能够在这个函数中打一些日志,辅助排查吗?
崩溃系统候,应该能够收集到崩溃时候的日志吧?

这个会不会是线程安全的问题。极端情况下比如触发handlePromiseExceptions的时候,又触发的onPromiseRejectCallback,这样2个线程会在同一时间修改_promiseArray。这样是不是可能引发crash?

应该不会是线程问题,onPromiseRejectCallback 只可能在主线程回调。JS 执行环境本身也是单线程的。
崩溃堆栈也是某个线程的堆栈,不同线程的堆栈是不会掺杂在一起的。

那如果要在这个函数中打印一些日志,有什么建议吗?不太清楚打印什么可以帮助排查这个crash问题。

可以在 handlePromiseExceptions 头和尾把 _promiseArray 打印一下,函数中间把 exceptions.event.c_str(), exceptions.stackTrace.c_str() 也打印一下。

这样加的话,基本上每帧都会输出日志,对性能影响大嘛?

判断 _promiseArray 不为空 后面再打,如果为空,就不打。只有在有 promise 异常的时候才会打印的。

Fixed in 3.8.4:

也重构了输出堆栈的格式,报错信息也更加详细了。

点赞:+1::+1::+1: