您的当前位置:首页正文

修复金山云KSYStreamer 在Android P以上机型Native Crash

2024-11-29 来源:个人技术集锦

问题

在升级了Target API28之后,发现我们一直使用的金山云的推流SDK在部分Android 9以上的手机离开开播页的时候会不明的出现Crash,我的小米8上面是固定第二次的时候Crash,一些手机第一次就Crash了,崩溃日志如下:

Abort message: 'FORTIFY: pthread_mutex_destroy called on a destroyed mutex (0xe60a6638)'
r0 00000000 r1 00004484 r2 00000006 r3 00000008
r4 00004484 r5 00004484 r6 ffc9d79c r7 0000010c
r8 00000000 r9 e60ce000 r10 ffc9d830 r11 e60ce000
ip ffc9d738 sp ffc9d788 lr e65b5139 pc e65ace56
backtrace:
#00 pc 0001ce56 /system/lib/libc.so (abort+58)
#1 pc 00064a63 /system/lib/libc.so (__fortify_fatal(char const*, ...)+26)
#2 pc 00064265 /system/lib/libc.so (HandleUsingDestroyedMutex(pthread_mutex_t*, char const*)+20)
#3 pc 00064919 /system/lib/libc.so (pthread_mutex_destroy+128)
#4 pc 000c969f /data/app/com.ksyun.live.demo-GHznaGLhejtsX-hu5CDo8w==/lib/arm/libksylive.so (AudioFilterBase::destroyFifo()+6)
#5 pc 000c96f3 /data/app/com.ksyun.live.demo-GHznaGLhejtsX-hu5CDo8w==/lib/arm/libksylive.so (AudioFilterBase::~AudioFilterBase()+14)
#6 pc 000ca27f /data/app/com.ksyun.live.demo-GHznaGLhejtsX-hu5CDo8w==/lib/arm/libksylive.so (AudioResample::~AudioResample()+50)
#7 pc 000ca291 /data/app/com.ksyun.live.demo-GHznaGLhejtsX-hu5CDo8w==/lib/arm/libksylive.so (AudioResample::~AudioResample()+4)

这可咋整啊?金山云都已经停止维护了,找作者也找不到啊!Github上面也有人在报这个问题(),不过也没有人能解决。自研的推流工具也还没有Ready。。。无奈只能自己逆向去尝试解决了:

这个报错是说我们重复销毁了一个互斥锁。挂在了Native层,但是很奇怪是为啥之前不会挂,但是现在就挂了?只能去读系统源码了。

查看系统源代码如下:

错误原因找到了,那我们怎么知道金山云到底做了啥导致的这个错误呢?我们先用IDA工具去分析一下Crash的地方:

#4 pc 000c969f /data/app/com.ksyun.live.demo-GHznaGLhejtsX-hu5CDo8w==/lib/arm/libksylive.so (AudioFilterBase::destroyFifo()+6)
 BL              audio_utils_fifo_deinit

这里挂掉了,看看内容如何:

调试过程

一开始我本来想用IDA的动态调试在我手机上直接去给函数打断点,无奈调试的时候总是卡死(小米的手机是真烂),懒得折腾,就用Hook工具去做调试了,由于这里要用Inline Hook,爱奇艺的xhook不能搞定,我这里就用的Dobby这个框架来做的Hook,代码如下:

static int my_audio_utils_fifo_init(unsigned int *a1, unsigned int a2, unsigned int a3, unsigned int a4) {
    int ret = old_audio_utils_fifo_init(a1, a2, a3, a4);
    __android_log_print(ANDROID_LOG_DEBUG, "mytag", "my_audio_utils_fifo_init");
    return  ret;
}
int  my_audio_utils_fifo_deinit(int a1) {
    __android_log_print(ANDROID_LOG_DEBUG, "mytag", "my_audio_utils_fifo_deinit");
    return 0;
}
 
void dobbyHook() {
    DobbyHook((void *) &audio_utils_fifo_init, (void *) my_audio_utils_fifo_init,
              (void **) &old_audio_utils_fifo_init);
    DobbyHook((void *) &audio_utils_fifo_deinit, (void *) my_audio_utils_fifo_deinit,
              (void **) &old_audio_utils_fifo_deinit);
}

由于old_audio_utils_fifo_deinit会导致Crash,所以我直接返回了0,不执行这一句了。接下来我们运行看看:

解决问题

这个问题其实看到这个崩溃就比较好解决。我想到了两种方案:

应很多网友要示例代码,我在GitHub创建了一个Repo,大家可以看看。

显示全文