1. 保存core dump文件
默认linux系统的core dump可能没有打开,因为core dump文件很大,会大量占用机器资源。为了保存core dump文件,需要运行前设置 ulimit -c unlimited
core文件会保存在当前目录下,并且只对当前终端有效,可以用命令修改core文件位置 sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t
2. backtrace辅助排查
线上服务一般占用内存较大,出core时,dump非常慢,gdb加载的时候也很慢。而大多数场景的core,结合堆栈和代码就可以确定。可以选择通过捕获信号、backtrace打印堆栈来辅助排查问题。
#include <signal.h>
#include <iostream>
#include <stdio.h>
#include <execinfo.h>
void handler(int sig) {
void *array[64];
int size = backtrace(array, 64);
std::cout << "Error: sig: " << sig << std::endl;
char** address = backtrace_symbols(array, size);
for (int i = 0; i < size; i++) {
std::cout << i << " : " << address[i] << std::endl;
}
free(address);
}
void baz() {
::raise(SIGABRT);
}
void bar() {
baz();
}
void foo() {
bar();
}
int main(void) {
::signal(SIGSEGV, &handler);
::signal(SIGABRT, &handler);
foo();
return 0;
}
这个代码会捕获abort信号,并将堆栈打印到标准输出。
执行编译 g++ core_backtrace.cpp -o ba -ggdb -rdynamic
运行结果:
这种实现方式不能应用到线上。线上可以直接使用boost实现的方法来打印到文件中。
#include <signal.h>
::signal(SIGSEGV, &my_signal_handler); //发SIGSEGV信号
::signal(SIGABRT, &my_signal_handler); //发SIGABRT信号
//捕获处理信号
#include <signal.h>
#include <boost/stacktrace.hpp>
void my_signal_handler(int signum) {
::signal(signum, SIG_DFL);
boost::stacktrace::safe_dump_to("./backtrace.dump");
::raise(SIGABRT);
}