三步搞定 ROS 进程崩溃 - Core Dump(亲测20.04同样适用)

18 篇文章 5 订阅

当程序运行的过程中异常终止或崩溃,Linux 操作系统会将程序当时的内存状态记录下来,保存在一个文件中,这种行为就叫做 Core Dump。 通俗的讲,Core Dump 有点类似于飞机失事的黑匣子。Core Dump 记录了程序崩溃时的 “内存快照”,记录了能够帮助程序猿诊断和定位崩溃原因的信息:包括内存信息、寄存器信息(包括程序指针、栈指针等)、内存管理信息、其他处理器和操作系统状态和信息等。正式商业化运行的程序崩溃往往是很难重现的,所以 core dump 文件记录的信息对程序猿非常有用,可以帮忙程序猿再现程序出错崩溃时的情景。

基于 ROS 开发时,也需要收集进程的崩溃时的 Core Dump 信息。本篇分享如何基于 Ubuntu18.04 + ROS melodic 配置 Core Dump 诊断 ROS 进程崩溃。

Apport

Ubuntu18.04 的默认 Core Dump 工具是 Apport。体验不友好,不推荐使用!

第一步:取消 core dump 文件大小限制

使用 ulimit -c 命令查看 ubuntu 系统当前的 core 文件大小。如果 core file size 为 0,则进程崩溃后不会产生 core dump 文件。需要取消 core file size 的文件大小限制。

修改 / etc/security/limits.conf,增加下面两行:

*               soft    core           unlimited
*               hard    core           unlimited

修改 / etc/pam.d/common-session 和 / etc/pam.d/common-session-noninteractive 添加下面一行:

session required pam_limits.so

修改~/.bashrc 添加下面一行:

ulimit -c unlimited

查看 ulimit,确认 core file size 已设置为 unlimited

$ulimit -a
core file size          (blocks, -c) unlimited

第二步:修改 Core Dump 文件产生路径和文件名

修改 / proc/sys/kernel/core_pattern 指定 core dump 文件保存位置和文件名格式。Ubuntu18.04 中默认值为 apport,必须替换掉!

$ cat /proc/sys/kernel/core_pattern 
|/usr/share/apport/apport %p %s %c %d %P %E               

修改文件命令:

echo core-%e-%p-%t | sudo tee /proc/sys/kernel/core_pattern               

上面命令使 core 文件生成到当前目录下,产生的文件名为 core - 命令名 - pid - 时间戳

以下是参数列表:

  • %p - insert pid into filename 添加 pid(进程 id)
  • %u - insert current uid into filename 添加当前 uid(用户 id)
  • %g - insert current gid into filename 添加当前 gid(用户组 id)
  • %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 添加导致产生 core 的命令名

第三步:添加 gdb 调试信息

在编译 ROS 进程的 CMakelist.txt 中添加下面命令,使编译产生的执行文件包含 gdb 调试信息。

SET(CMAKE_BUILD_TYPE "Debug")  
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")

CMAKE_BUILD_TYPE 是 CMake 中的一个变量,可以的取值是

  • Debug
  • Release
  • RelWithDebInfo
  • MinSizeRel

当这个变量值为 Debug 时,CMake 会使用变量 CMAKE_CXX_FLAGS_DEBUG 和 CMAKE_C_FLAGS_DEBUG 中的字符串作为编译选项生成 Makefile,相应的编译选项就是在这里指定。

CMAKE_CXX_FLAGS_DEBUG 中的编译选项解释:

  • -O0 关闭所有代码优化选项
  • -Wall 开启大部分告警提示
  • -g 包含调试信息
  • -ggdb 在可执行文件中包含可供 gdb 使用的调试信息

CMAKE_CXX_FLAGS_RELEASE 中的编译选项解释:

  • -O3 开启第三级别优化,在 - O2 基础上增加产生 inline 函数、使用寄存器等优化技术

验证:

构造 segmentation fault

创建一个 ROS 包并构造一个 segmentation fault,触发生成 core dump。

#include <ros/ros.h>
#include <iostream>

int main(int argc, char **argv){
    ros::init(argc, argv, "core_dump_test");
    ros::NodeHandle n;    
    int *p = NULL;
    std::cout<<*p<<std::endl; //使用空指针

    ros::AsyncSpinner spinner(1);
    spinner.start();
    ros::waitForShutdown();
}


编译成功后,使用 roslaunch 命令启动 ROS 进程,产生段错误:

$roslaunch core_dump_test core_dump_test.launch 
... logging to /home/jinchengcowboy /.ros/log/8e44d422-7929-11ec-9bb9-000c29942a36/roslaunch-jinchengcowboy -virtual-machine-6919.log
Checking log directory for disk usage. This may take a while.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.

started roslaunch server http://jinchengcowboy-virtual-machine:42357/

SUMMARY
========

PARAMETERS
 * /rosdistro: melodic
 * /rosversion: 1.14.12

NODES
  /
    core_dump_test (core_dump_test/core_dump_test)

auto-starting new master
process[master]: started with pid [6930]
ROS_MASTER_URI=http://localhost:11311

setting /run_id to 8e44d422-7929-11ec-9bb9-000c29942a36
process[rosout-1]: started with pid [6941]
started core service [/rosout]
process[core_dump_test-2]: started with pid [6944]
[core_dump_test-2] process has died [pid 6944, exit code -11, cmd /home/jinchengcowboy /git_prj/ros_example/devel/lib/core_dump_test/core_dump_test __name:=core_dump_test __log:=/home/jinchengcowboy/.ros/log/8e44d422-7929-11ec-9bb9-000c29942a36/core_dump_test-2.log].

roslaunch 时 core dump 文件生成的位置在 $ROS_HOME 下,如未配置默认在~/.ros 目录下

$ ll ~/.ros/|grep core 
-rw-------  1 jinchengcowboy jinchengcowboy 43876352 1月  19 15:07 core-core_dump_test-7740

gdb 查看 core dump 文件

本人实测:
gdb ./devel/lib/agv_navigate/agv_navigate_node ~/.ros/core-agv_navigate_no-333528-1673057645

$ gdb ./devel/lib/core_dump_test/core_dump_test ~/.ros/core-core_dump_test-7740
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./devel/lib/core_dump_test/core_dump_test...done.
[New LWP 7740]
[New LWP 7742]
[New LWP 7744]
[New LWP 7749]
[New LWP 7743]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `/home/jinchengcowboy/ros_example/devel/lib/core_dump_test/core_dump_test __name:=core_d'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000055645c872d92 in main (argc=1, argv=0x7ffe33b138d8) at /home/jinchengcowboy/ros_example/src/core_dump_test/src/main.cpp:8
8	    std::cout<<*p<<std::endl;
[Current thread is 1 (Thread 0x7f7ae02ca780 (LWP 7740))]
(gdb) bt
#0  0x000055645c872d92 in main (argc=1, argv=0x7ffe33b138d8) at /home/jinchengcowboy/ros_example/src/core_dump_test/src/main.cpp:8
(gdb) 

本文中所有代码可在 gitee 工程上查询到:

wangnanxi/ros_example​gitee.com/wangnanxi/ros_example​gitee.com/wangnanxi/ros_example

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值