这是一个耗时一个多月才解决的native crash(2)

2023年 10月 12日 103.9k 0

一、背景

1、长久以来,线上长期出现关于socket native crash的闪退(此类型大部分是后台闪退,没有用户反馈使用app的过程中出现闪退)

内容如下:

Thread-1504(24253)

SIGSEGV(SEGV_MAPERR)
解析原始
1
#00 pc 00000000000b396c /data/app/~~mSyo_ZlnL5Gr3SuMGGseVA==/com.xx.seeyou-LAWMFJQ7xddipfrQ6MVimw==/lib/arm64/libclientsdk.so [arm64-v8a::de63b5e1d2007ebbad9c3e7b9001d192]
2
#01 pc 00000000000b3980 /data/app/~~mSyo_ZlnL5Gr3SuMGGseVA==/com.linxxgan.seeyou-LAWMFJQ7xddipfrQ6MVimw==/lib/arm64/libclientsdk.so [arm64-v8a::de63b5e1d2007ebbad9c3e7b9001d192]
3
#02 pc 00000000000b3a10 /data/app/~~mSyo_ZlnL5Gr3SuMGGseVA==/com.linxxgan.seeyou-LAWMFJQ7xddipfrQ6MVimw==/lib/arm64/libclientsdk.so [arm64-v8a::de63b5e1d2007ebbad9c3e7b9001d192]
4
#03 pc 00000000000b2d30 /data/app/~~mSyo_ZlnL5Gr3SuMGGseVA==/com.x.seeyou-LAWMFJQ7xddipfrQ6MVimw==/lib/arm64/libclientsdk.so [arm64-v8a::de63b5e1d2007ebbad9c3e7b9001d192]
5
#04 pc 00000000000b20e4 /data/app/~~mSyo_ZlnL5Gr3SuMGGseVA==/com.xx.seeyou-LAWMFJQ7xddipfrQ6MVimw==/lib/arm64/libclientsdk.so [arm64-v8a::de63b5e1d2007ebbad9c3e7b9001d192]
6
#05 pc 000000000006bd04 /data/app/~~mSyo_ZlnL5Gr3SuMGGseVA==/com.xx.seeyou-LAWMFJQ7xddipfrQ6MVimw==/lib/arm64/libclientsdk.so [arm64-v8a::de63b5e1d2007ebbad9c3e7b9001d192]
7
#06 pc 00000000000745cc /data/app/~~mSyo_ZlnL5Gr3SuMGGseVA==/com.xx.seeyou-LAWMFJQ7xddipfrQ6MVimw==/lib/arm64/libclientsdk.so [arm64-v8a::de63b5e1d2007ebbad9c3e7b9001d192]
8
#07 pc 00000000000eb828 /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+64) [arm64-v8a::5f57d25b37c043ed36c0e4147dcc8b3f]
9
#08 pc 000000000008ba48 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) [arm64-v8a::5f57d25b37c043ed36c0e4147dcc8b3f]
10
java:
11
[Failed to get Java stack]

由于大部分都是后台闪退,不影响用户使用,原因可能是系统后台回收导致,因此在854版本以前,长期以来,我们使用bugly 对socket的libclientsdk.so库的闪退进行的屏蔽,以方便整体闪退率的统计;

2、然而,在854版本上线后,出现了以下的前台闪退,用于的反馈是:”一打开就闪退“或者”每次都要打开好几次才能进入app“

内容如下:

SIGABRT
解析原始
1
#00 pc 000000000007066c /apex/com.android.runtime/lib64/bionic/libc.so (abort+160) [arm64-v8a::b91c775ccc9b0556e91bc575a2511cd0]
2
#01 pc 00000000000babec /apex/com.android.runtime/lib64/bionic/libc.so (__stack_chk_fail+20) [arm64-v8a::b91c775ccc9b0556e91bc575a2511cd0]
3
#02 pc 0000000000067d5c /data/app/com.zz.seeyou-6mpLTCQW-oI4eWYYjRA5EQ==/lib/arm64/libclientsdk.so [arm64-v8a::de63b5e1d2007ebbad9c3e7b9001d192]
4
#03 pc 0000000000067e4c /data/app/com.xx.seeyou-6mpLTCQW-oI4eWYYjRA5EQ==/lib/arm64/libclientsdk.so [arm64-v8a::de63b5e1d2007ebbad9c3e7b9001d192]
5
#04 pc 000000000006cb78 /data/app/com.xx.seeyou-6mpLTCQW-oI4eWYYjRA5EQ==/lib/arm64/libclientsdk.so [arm64-v8a::de63b5e1d2007ebbad9c3e7b9001d192]
6
#05 pc 000000000007310c /data/app/com.xx.seeyou-6mpLTCQW-oI4eWYYjRA5EQ==/lib/arm64/libclientsdk.so [arm64-v8a::de63b5e1d2007ebbad9c3e7b9001d192]
7
#06 pc 000000000006cf18 /data/app/com.xx.seeyou-6mpLTCQW-oI4eWYYjRA5EQ==/lib/arm64/libclientsdk.so [arm64-v8a::de63b5e1d2007ebbad9c3e7b9001d192]
8
#07 pc 00000000000745b8 /data/app/com.xx.seeyou-6mpLTCQW-oI4eWYYjRA5EQ==/lib/arm64/libclientsdk.so [arm64-v8a::de63b5e1d2007ebbad9c3e7b9001d192]
9
#08 pc 00000000000cf7c0 /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+36) [arm64-v8a::b91c775ccc9b0556e91bc575a2511cd0]
10
#09 pc 00000000000721a8 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) [arm64-v8a::b91c775ccc9b0556e91bc575a2511cd0]

通过之前的文章:juejin.cn/spost/72886…

我们解决了因为升级bugly sdk 导致 app启动后 概率性的 在未进入首页后立刻出现crash的问题;

主要原因是,新版bugly 废弃了屏蔽功能,并且启动app的时候会偶发性的触发某个回调,造成KillProcess。

在855临近封包的一两天,我们的解决方案是:去除屏蔽socket libclientsdk.so库的闪退,去除bugly的回调,禁止调用KillProcess。

最后我们在复盘后了遗留了2个问题和1个待办:

2个问题是:

    1、socket的crash 是如何发生的,没有定位到;

    2、socket的闪退类型是:SIGABRT,而不是SIGSEGV,也就是说,从后台闪退,变成了前台闪退,但是很久以来,Socket库本身没有更新,也没有找造成socket闪退对应的原因;

1个待办是:

   1、提升定位native crash的能力

3、随着855版本,依然出现了2的闪退,只是从用户反馈的情况上看,现象变成了:" 进入首页后,才发生的闪退 "

二、排查过程

1、通过学习,我们先掌握了排查socket native crash的以下技能

  • 熟练掌握addr2line工具的使用

  • 了解了不同ndk打包出的so的pc堆栈可能是不一样的;比如线上的socket so库是ndk r10e打包的,新版我们采用ndk r22打包;

  • 通过不断的阅读socket库的源码,逐步熟悉了整个库要如何编译,如何运行,以及编译的产物,以及一些编译属性的影响;

2、排查思路

  • 不论是业务引发的闪退,还是socket库本身的闪退,一切以闪退日志为源头开始排查,不采取 ”通过需求检查或者代码review的方式进行排查“,这种方式找到概率性闪退根源的概率微乎其微;

  • 我们打算通过重新编译 socket debug so库,让测试通过压测等手段,尝试复现出闪退;

  • 通过addr2line命令,查找到闪退的代码行;

  • 根据查找到的代码行,找到解决方案;

1、历史so库版本的追溯,确认追溯方案

     经过一翻追溯,我们发现线上版本的so库,是2020-1-20打包的,历史太悠久,当时打包的时候,并没有保留对应的debug.so库(新版本已经规范化,保留全部产物),因此无法使用add2line工具找到对应的代码行;

并且我们尝试过通过追溯聊天记录,使用ndk r10e重新编译2020年的代码,但是也匹配不上,这种方式可能无法追溯了,主要是因为就算追溯到了,也不敢保证追溯的代码行数是对的,可能会造成方向误导;

所以我们还是决定,重新编译so库;

我们先编译了个一个debug.so库,并手动构造了一个native crash,内容如下,主要用于确认debug.so库闪退的时候,是可以直接看到堆栈和函数的:

Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x9c in tid 30316 (example.meetyou), pid 30272 (example.meetyou)
2023-04-07 15:16:59.288 30320-30320 DEBUG                   crash_dump64                         A  Softversion: PD2020C_A_7.10.11
2023-04-07 15:16:59.288 30320-30320 DEBUG                   crash_dump64                         A  Time: 2023-04-07 15:16:59
2023-04-07 15:16:59.288 30320-30320 DEBUG                   crash_dump64                         A  *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
2023-04-07 15:16:59.288 30320-30320 DEBUG                   crash_dump64                         A  Build fingerprint: 'vivo/PD2020/PD2020:10/QP1A.190711.020/compiler02071532:user/release-keys'
2023-04-07 15:16:59.288 30320-30320 DEBUG                   crash_dump64                         A  Revision: '0'
2023-04-07 15:16:59.288 30320-30320 DEBUG                   crash_dump64                         A  ABI: 'arm64'
2023-04-07 15:16:59.288 30320-30320 DEBUG                   crash_dump64                         A  Timestamp: 2023-04-07 15:16:59+0800
2023-04-07 15:16:59.288 30320-30320 DEBUG                   crash_dump64                         A  pid: 30272, tid: 30316, name: example.meetyou  >>> com.example.meetyou 1024,则不让连接通道创建。避免fd_set 超过 FD_SETSIZE 超时应用退出情况。弊端im和站内信将无法使用,根治需要确认app 大量文件描述符未关闭问题

7、后续待推进事项:

  • 排查App使用fd过多的场景以及治理方案确认和执行
  • 完善Socket测试用例;
  • Socket库废弃select方案,改为epoll方案,因为app其实是用可能使用fd超过1024的。
  • 为何线上闪退的堆栈和我们复现的堆栈有一点点不一样?这是因为FD_SET是ndk的,不同版本的ndk实现源码不一致;

8、最终结论:

 1、经过856版本5w用户的灰度,已经确认Socket前台闪退已修复,还有一个后台socket闪退堆栈已抓到,已发给xx定位;
2、闪退直接原因:用户使用app fd数量超过1024,触发socket select框架的限制,然后闪退;
3、为什么从854和855版本开始发生:我们通过抓去用户超过本地fd的文件情况发现,大部分用户使用都在1024以下,小部分在1100左右,有发现一个在1600左右,
通过分析,触发时机基本都是在启动后 图片上传引起的:图片上传开启多线程并发,以及操作数据库,OSS上传等,均会使用较多fd,所以辣妈身份的概率会大一些;
从854和855开始主要原因归结为:因为业务使用fd增量以及855版本开启了多线程上传,导致fd的使用在某一瞬间突破临界值;

后续方案:
1、全局治理fd
2、由于无法精确控制app整体fd不能超过1024(业务+第三方,系统通讯等),现在设备基本可开放的fd都是3w多,若要兼容这部分用户的IM功能正常稳定,建议socket后续采用epoll方案实践,废弃select方案;

相关文章

服务器端口转发,带你了解服务器端口转发
服务器开放端口,服务器开放端口的步骤
产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
如何使用 WinGet 下载 Microsoft Store 应用
百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

发布评论