目录

forkdump 触发的神奇 bug

​ 最近在修改私有化的 hprof dump 的库,这个库因为当时对比了koom 和 tailor

koom fork 子进程对应用影响小,但是 tailor 裁剪的 profile 文件更小,所以最终将两者结合在了一起

最近在修改的时候无意间触发了一个神奇的 bug

一行 Log 导致 crash

try {
    // fork 进程
    int pid = suspendAndFork();
    // 随便打印一行 log,触发一个 stringbuilder 方法
    Log.i(TAG, "test!" + dumpRes);
    if (pid == 0) {
        // dump 
        dumpHprofData(path, true);
        exitProcess();
    } else if (pid > 0) {
        // Parent process
        dumpRes = resumeAndWait(pid);
    }
} catch (IOException e) {
    Log.e(TAG, "dump failed caused by " + e.toString());
    e.printStackTrace();
}

上述代码是 java 层的部分代码

suspendAndFork 就是借鉴的 koom 的部分代码,实际作用是 fork 进程

接下来的一行 log,在 Android 11 及以上版本执行,子进程必定 crash

而删掉这行 log,子进程正常执行后续的 heap dump 逻辑

就是这么神奇

可能的原因

目前还不知道真实的原因,不过调用堆栈都指向 jit-cache

通过搜索一些文章发现,jit 在 Android11 似乎也有变动,猜测非常可能与之相关

通过 madvise() 设置 MADV_DONTFORK 确保可写的那份映射无法被子进程访问。Fork 之后,子进程对应的可写映射记录丢失,访问将触发 SIGSEGV。

https://juejin.cn/post/7077563723082104839