Some Experiences With Core Dump

2020-12-30 by xiaoguang

我一直写 Java/Scala/C# 这类的“托管”语言,很少用 core dump,最近解决了一个 ScyllaDB core dump 失败的问题,补充了很多相关的知识,在这里总结下。

(本文不涉及如何 read/debug core dump 文件)

系统配置

在 linux 下使用 man core 可以看到非常详细的关于 core dump 的说明。当应用程序发生崩溃,或者收到了一个特定的 signal(比如 SIGABRT,见下文)时,kernel 会将该应用当前的运行状态 dump 出来,内容包括当前 cpu 指令、堆栈、应用当前的内存状态等。

core dump 输出路径配置在 /proc/sys/kernel/core_pattern 里, 比如:

$ cat /proc/sys/kernel/core_pattern
/var/crash/core-%e-%s-%u-%g-%p-%t

core dump 文件名相关的参数可以参考 man core。kernel 除了能将 core 文件直接写入磁盘外,也可以在生成时直接将字节内容 pipe 给第三方程序,比如 systemd 或者 ABRT (AUTOMATIC BUG REPORTING TOOL),这样的好处时,所有 core dump 能够被统一收集、管理,并且第三方程序能够在采集 core dump 内容的同时采集更多的环境信息。

$ cat /proc/sys/kernel/core_pattern
|/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %e
# Or for CentOS:
#|/usr/libexec/abrt-hook-ccpp %s %c %p %u %g %t %h %e 636f726500

当 core dump 被重定向到第三方应用时,有可能会因为第三方应用的 bug 导致即使 core dump 生成了,我们也没有能在磁盘上找到相关文件。类似的 BUG 比如:

$ journalctl|grep systemd
Dec 28 09:46:03 dmp-scylla4-01 systemd-coredump[28766]: Failed to send coredump datagram: Message too long
Dec 28 09:46:03 dmp-scylla4-01 systemd[1]: Started Process Core Dump (PID 28766/UID 0).
Dec 28 09:46:03 dmp-scylla4-01 systemd-coredump[28770]: Coredump file descriptor missing.

此时除了升级最新的第三方程序外,一个快速的解决办法可能就是绕过三方程序,让 kernel 将 core dump 直接写入磁盘。

FYI, 此外,在使用 systemd-coredump 的环境,可以通过 coredumpctl 来查找、管理系统内所有的 core dump 事件。

目标进程配置

另外,core dump 能否生成,也依赖于目标进程的 resource limits 参数设置,其中 RLIMIT_CORE 限制了 core 文件的大小,RLIMIT_FSIZE 限制了任何文件的大小。因此在生成 core dump 前,需要确保当前进程 limits 参数没有问题,如:

$ cat /proc/507/limits
Limit                     Soft Limit           Hard Limit           Units
Max cpu time              unlimited            unlimited            seconds
Max file size             unlimited            unlimited            bytes
Max data size             unlimited            unlimited            bytes
Max stack size            8388608              unlimited            bytes
Max core file size        unlimited            unlimited            bytes
Max resident set          unlimited            unlimited            bytes
Max processes             8096                 8096                 processes  

如果参数为 0 或者过小,可以通过 prlimit 工具进行调整。

生成 core dump

core dump 除了在进程发生 crash 时发生外,也可以手动触发,参考 man signal, 所有 Action 为 CORE 的 signal 都可以触发 core dump(目标进程有可能修改 signal 默认的处理行为),比如 SIGABRT 或者 SIGSEGV:

kill -s SIGSEGV <pid>