【linux】coredump问题排查

55 篇文章 4 订阅
14 篇文章 1 订阅

 

序言

  • 记录coredump问题的一些定位技巧

1. coredump简介

  • coredump称为核心转储,就是在进程异常时的一个快照,保存了异常时的内存、寄存器、堆栈等数据
  • 当进程接收到某些 信号 而导致异常退出时,就会生成 coredump 文件
  • core文件是ELF文件格式,可通过readelf读取查看其信息

2. 常见的coredump错误

2.1 哪些信号会导致coredump
2.1 coredump的常见原因
2.2.1 非法指针
  • 使用空指针:指针为空,但仍然访问其成员;或指针已经释放又再次直接访问
  • 对未初始化的指针进行了操作
  • 内存double free:多次释放同一段内存
  • 随意使用指针转换:一个指向一段内存的指针,可能这段内存的开始地址就是按照某种结构或者类型对齐的,如果随意进行指针类型转换,可能导致bus error或coredump
  • 存在野指针:内存释放后,指针为赋值为nulptr。这个原因只是我个人猜想
2.2.2 内存越界访问
  • 数组下标越界:比如未检查传参元素个数,下标超了max_size
  • 搜索字符串时以字符串结束符作为判断条件,但字符串可能没有正常使用结束符
  • 使用了非安全的字符串操作函数:如使用strcpy, strcat, sprintf, strcmp, strcasecmp等字符串操作函数,将目标字符串读/写爆。应该使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等安全函数防止读写越界
2.2.3 多线程原因
  • 多线程使用了线程不安全函数:应使用可重入函数asctime_r(3c) gethostbyname_r(3n) getservbyname_r(3n) ctermid_r(3s) gethostent_r(3n) getservbyport_r(3n) ctime_r(3c) getlogin_r(3c) getservent_r(3n) fgetgrent_r(3c) getnetbyaddr_r(3n) getspent_r(3c) fgetpwent_r(3c) getnetbyname_r(3n) getspnam_r(3c) fgetspent_r(3c) getnetent_r(3n) gmtime_r(3c) gamma_r(3m) getnetgrent_r(3n) lgamma_r(3m) getauclassent_r(3) getprotobyname_r(3n) localtime_r(3c) getauclassnam_r(3) etprotobynumber_r(3n) nis_sperror_r(3n) getauevent_r(3) getprotoent_r(3n) rand_r(3c) getauevnam_r(3) getpwent_r(3c) readdir_r(3c) getauevnum_r(3) getpwnam_r(3c) strtok_r(3c) getgrent_r(3c) getpwuid_r(3c) tmpnam_r(3s) getgrgid_r(3c) getrpcbyname_r(3n) ttyname_r(3c) getgrnam_r(3c) getrpcbynumber_r(3n) gethostbyaddr_r(3n) getrpcent_r(3n)等
  • 多线程读写的数据未加保护:会被多个线程同时访问的全局数据应该加保护,否则很容易导致coredump;
2.2.4 堆栈溢出
  • 不要使用太大的局部变量,容易造成堆栈溢出,导致一些奇怪的错误
2.2.5 字节对齐原因

看到有的文章列的原因,目前没有碰到过

  • 字节对齐方式引起的程序核心转储
  • 引用模块与自身模块所定义的结构体的字节对齐方式不同
  • 在代码中, 把引用到的别的模块的头文件包含到自身文件中的字节对齐方式语法声明的中间了, 结果导致字节对齐方式出现了变化

3. 如何生成coredump文件

  • 为了生成coredump文件,编译选项中需要添加-g选项

  • 添加-g后可使用gdb调试,调用栈也能显示行号

3.1 先看系统是否允许生成coredump文件
ulimit -c
  • 0:表示禁止产生coredump文件
  • unlimited: 表示不限制coredump文件的大小
  • 1024: 表示coredump文件大小不能超过1024K
3.2 设置允许coredump文件生成
3.2.1 设置当前会话生效
ulimit -c 1024		// 或其他数值/unlimited
3.2.2 设置对当前用户生效
  • 在~/.bashrc或者~/.bash_profile中进行配置
ulimit -c unlimited
3.2.3 设置系统生效
  • 在/etc/security/limits.conf文件中进行配置

  • vim /etc/security/limits.conf

  • 配置如下字段:

    <domain><type><item><value>
    *softcoreunlimited
3.3 设置coredump文件的存储位置
  • 先看默认配置:cat /proc/sys/kernel/core_pattern
3.3.1 修改方式1
echo "/corefile/core-%e-%p-%t" > /proc/sys/kernel/core_pattern
  • 将会在/corefile目录下生成e-线程名-p-进程号-t时间戳的core文件
3.3.2 修改方式2
sysctl -w kernel.core_pattern=/corefile/core-%e-%p-%t
3.3.3 修改方式3:对系统生效
  • 在/etc/sysctl.conf中添加配置

    kernel.core_uses_pid = 1
    kernel.core_pattern = /your/own/path/core_%e_%p_%t
    
  • 然后执行:

    sysctl -p
    
  • 查看cat /proc/sys/kernel/core_pattern如果设置未生效则可在目标目录如corefile下执行sysctl -p或者重启电脑后执行sysctl -p

【参数含义】

%p - insert pid into filename 添加pid
%u - insert current uid into filename 添加当前uid
%g - insert current gid into filename 添加当前gid
%s - insert signal that caused the coredump into the filename 添加导致产生core的信号
%t - insert UNIX time that the coredump occurred into filename 添加core文件生成时的unix时间
%h - insert hostname where the coredump happened into filename 添加主机名
%e - insert coredumping executable name into filename 添加命令名
  • 注:vscode调试时发生coredump后右键选择copy call stack也可以保存

4. 如何排查coredump问题

4.1 问题能复现
4.1.1 debug模式下gdb运行
  • debug模式下使用,即编译选项加-g

    gdb 可执行文件
    r	# 运行
    bt	# 查看调用栈
    
  • bt或where查看调用栈

  • 如果是多线程可通过如下命令查看每个线程的调用栈情况

    info thread				# 查看所有线程
    thread apply all bt		# 查看所有线程的调用栈情况
    
  • gdb常用命令汇总

4.1.2 coredump发生时记录core文件
  • 按照3中的流程打开core文件设置,使程序能在coredump文件发生时记录core文件

  • 但要防止core文件过大,需要定期清理

  • 拿到core文件后执行如下语句复现问题

    gdb executable_file core_file
    
4.1.3 log辅助定位
  • 使用glog打印,节点运行过程中记录log,节点掉线保存log过后查看日志信息
  • 一种方法是使用glog日志框架添加和保存日志;
  • 一种是比较简单的std::cout/printf添加日志并:executable_file > log.txt 2>&1保存为文件查看

【本地复现】

  • 本地gdb executable_file长时播包测试直到问题复现

  • 最好也设置core文件存储,否则因为其他原因导致系统死机无法查看现场

4.2 问题不能复现
4.2.1 代码review
  • 确认问题引入的时间段,针对性的进行代码review找出可能导致coredump的原因
  • 但是当问题引入时间不明确,或者代码特别多的时候,这种方法可能不太实用
4.2.2 使用valgrind查内存问题
4.2.3 针对常见coredump问题原因进行排查
  • 是否有空指针未判空访问
  • 是否有内存泄漏或者内存double free等
  • 是否有数组越界访问
  • 是否多线程全局变量未加保护访问
4.3 容器创建时设置core文件存储
  • 容器内启动的程序,可在容器创建时设置core文件存储,设置方式见3.3章节

  • 通过设置Dockerfile中CMDENTRYPOINT命令来设置,dockerfile创建镜像命令

    • CMD:容器启动时执行的命令,这些命令在docker run时执行
    • ENTRYPOINT:容器启动时执行的命令,与CMD类似
    • CMD会被docker run时添加的参数覆盖,ENTRYPOINT不会被覆盖
  • 可设置自动设置脚本setenv.sh如下

    #! /bin/bash
    sysctl -w kernel.core_pattern=/corefile/core-%e-%p-%t
    sysctl -p
    
  • 修改文件权限

    chmod 777 setenv.sh
    
  • 然后Dockerfile中添加

    CMD ["./setenv.sh"]
    

【参考文章】
如何配置生效core文件
配置生效core文件和压缩coredump文件
coredump问题排查方法
coredump常见原因1
coredump常见原因2
coredump常见原因3
coredump文件是如何产生的 (推荐)
除gdb外的其他定位coredump方法

created by shuaixio, 2022.11.20

### 回答1: Linux中的core dump是指当程序由于意外错误或异常而崩溃时,系统将程序的内存内容转储到一个文件中,以便后续进行分析。下面是关于如何分析Linux core dump的步骤: 1. 确定core dump文件的位置:默认情况下,core dump文件保存在程序的当前工作目录。你可以使用`ulimit -c`命令来检查核心转储文件的大小限制,或者使用`sysctl kernel.core_pattern`命令查看核心转储文件的位置和名称模式。 2. 确保系统已经安装了相应的调试工具:在分析core dump之前,你需要安装GDB(GNU调试器),它是一个常用的用于调试程序和分析core dump的工具。使用`gdb`命令可以启动GDB。 3. 使用GDB加载core dump文件:在GDB命令行中,使用`gdb <程序名称> core`命令来加载core dump文件。这将打开GDB并加载core dump文件供分析。 4. 分析core dump文件:一旦core dump文件被加载到GDB中,你就可以进行分析了。你可以使用`bt`命令查看程序崩溃时的堆栈跟踪信息,这将有助于定位程序中的错误。你还可以使用其他GDB命令来检查变量的值,查找内存泄漏等。 5. 修复错误并重新编译程序(可选):根据core dump的分析结果,你可以找到程序中的错误并进行修复。之后,你可以重新编译程序并进行测试,以确保问题已解决。 总结起来,通过分析Linux core dump,我们可以确定程序崩溃的原因,并找到解决问题的方法。使用GDB等调试工具可以帮助我们更深入地了解程序内部的情况,从而提高代码的质量和稳定性。 ### 回答2: 在Linux系统中,coredump是指在程序发生异常导致崩溃时生成的包含程序内存和寄存器状态等信息的文件。通过分析coredump,我们可以了解程序崩溃的原因,从而进行故障排查问题修复。 首先,我们需要使用gdb工具来分析coredump文件。可以通过以下命令来加载coredump文件: gdb 可执行文件路径 core文件路径 然后,我们可以使用gdb提供的一系列命令进行分析,如下: 1. bt:打印出崩溃时的函数调用栈,可以查看崩溃发生的位置和函数调用关系; 2. info registers:显示程序崩溃时寄存器的状态,包括程序计数器、堆栈指针等,可以帮助我们了解程序崩溃时寄存器的值; 3. print 变量名:打印出指定变量的值,可以了解程序崩溃时变量的取值情况; 4. x/地址:打印出指定地址的内存内容; 5. info sharedlibrary:显示程序崩溃时加载的动态链接库信息; 6. source 源代码路径:加载源代码文件,可以查找对应的源代码以进行分析。 通过以上命令,我们可以逐步了解coredump文件中的信息,找出程序崩溃的原因。常见的导致程序崩溃的原因包括空指针引用、数组越界、内存泄漏等。根据不同情况,我们可以调试代码并修复问题。 总而言之,分析coredump是一种定位和解决程序崩溃问题的重要方法,通过分析coredump文件,我们可以了解程序崩溃的原因,并根据相应的信息进行修复。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值