Crash排查系列第十篇|Handler native crash排查

887 阅读1分钟

背景:版本灰度出现了handler相关奇怪的crash,不管是init,poll,wake都会出现类似crash

image.png

问题分析

Looper::wake 看上去是mWakeEventFd write时出问题了

void Looper::wake() {

#if DEBUG_POLL_AND_WAKE

    ALOGD("%p ~ wake", this);

#endif



    uint64_t inc = 1;

    ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd.get(), &inc, sizeof(uint64_t)));

    if (nWrite != sizeof(uint64_t)) {

        if (errno != EAGAIN) {

            LOG_ALWAYS_FATAL("Could not write wake signal to fd %d (returned %zd): %s",

                             mWakeEventFd.get(), nWrite, strerror(errno));

        }

    }

}

在logcat中发现了如下日志,这个时候可以大概率确认是谁把我们的fd给close了。

image.png

到底谁把我们close呢? 线上crash率只有万分之一,想正常复现很难。

  1. 观察crash设备表现,都发生在启动时机。找到启动改动的点。
  2. Android 10以上 一般java 层使用到的fd 都有closed判断,怀疑是native的问题,找到版本改动的so
  3. 一顿修改代码search后 发现一个怀疑点。

image.png

image.png 这边会是去关闭两次fd的。

  1. 关闭上面模块代码开关后,crash不再发生了。

继续分析

虽然上面问题解决了,我们继续分析,尝试去复现一下。

image.png 成功复现 image.png

监控方案

上面的方法发现并解决这个问题 运气占很大成分,想好后续如果再出现类似问题,如何精准定位才是关键。

android.googlesource.com/platform/bi… AOSP文档

android 10以上 有专门的fdsan用于监控排错。

把fdsan level设为 ANDROID_FDSAN_ERROR_LEVEL_FATAL 报下面错误,按照下面堆栈我们就能正确找到多次close的地方了

image.png