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。