因客户需要, 需要在我们的L1 程序发生段错误segmentation fault后, 要用消息的方式让高层知道。以前每次都要提供core dump 文件, 有些同学又不会看。
于是想到用信号函数来处理segmentation fault 信号, 并在这个时候发消息给L2。 另外为了方便定位, 我们需要自己知道是挂在哪一行了。
经过研究, 以下是可以直接用的代码:
1. C 代码中注册段错误的回调函数。
#include <iostream>
#include <execinfo.h>
static void printStackTrace() {
void* callstack[10];
int frames = backtrace(callstack, 10);
char** strs = backtrace_symbols(callstack, frames);
FILE* file = fopen("segmentationFaultInfo.txt","w");
if (file == NULL) {
return -1;
}
std::cout << "Stack trace:" << std::endl;
for (int i = 0; i < frames; ++i) {
std::cout << strs[i] << std::endl;
fprintf(file, "%s\n", strs[i]); // 存到文件后续解析
}
fclose(file);
free(strs);
system("./parseSegmentationFault.sh"); // 解析行数
}
static void sig_handler(int signum)
{
// phy thread is running in background, this will be triggered by "kill -2 {pid}"
if (SIGINT == signum )
exit_task_g = 1;
else if (SIGSEGV == signum) {
printf("\nSegmentation Fault caught!\n");
printStackTrace(); // 打印堆栈信息
exit(1);
}
}
int main(int argc, char **argv)
{
signal(SIGSEGV, sig_handler); // 注册段错误信号
uint8* p = NULL;
*p = 1; // 构造的段错误代码。
}
2. 写一个脚本解析是挂在哪一行了。
parseSegmentationFault.sh
appname=phycApp // 可执行文件名
logFile=./segmentationFaultInfo.txt
parseLog()
{
echo "Start to pase segmeationFaultInfo:"
cat $logFile
addrLines=`cat $logFile|grep $appname`
while IFS= read -r line; do
tmpAddr=`echo $line|sed "s/.*\[\(0x.*\)\].*/\1/g"`
echo "[addr $tmpAddr]:"
addr2line -Cif -e $appname $tmpAddr
done <<< "$addrLines"
}
if [ -e $logFile ];then
parseLog
else
echo "Error: $logFile is not exist !!!"
fi
3. 运行程序后可以打印出具体的行:
Segmentation Fault caught!
Stack trace:
./dpdk_bphy_phy() [0x440058]
linux-vdso.so.1(__kernel_rt_sigreturn+0) [0xffff819d05f4]
./dpdk_bphy_phy() [0x406c68]
/lib64/libc.so.6(__libc_start_main+0xe4) [0xffff81361024]
./dpdk_bphy_phy() [0x40a1b8]
Start to pase segmeationFaultInfo:
./dpdk_bphy_phy() [0x440058]
linux-vdso.so.1(__kernel_rt_sigreturn+0) [0xffff819d05f4]
./dpdk_bphy_phy() [0x406c68]
/lib64/libc.so.6(__libc_start_main+0xe4) [0xffff81361024]
./dpdk_bphy_phy() [0x40a1b8]
[addr 0x440058]:
printStackTrace
/data/jenkins/workspace/FM_5_DD_PHy@2/f95_nr_bphy/nr_phy_arm/build/../src/_AppMain.cpp:229
sig_handler
/data/jenkins/workspace/FM_5_DD_PHY_@2/f95_nr_bphy/nr_phy_arm/build/../src/_AppMain.cpp:255
sig_handler
/data/jenkins/workspace/FM_5_DD_PHY_@2/f95_nr_bphy/nr_phy_arm/build/../src/_AppMain.cpp:247
[addr 0x406c68]:
main
/data/jenkins/workspace/FM_5_DD_PHY_@2/_nr_bphy/nr_phy_arm/build/../src/_AppMain.cpp:3378 (这就是空指针那行)
[addr 0x40a1b8]:
_start
/home/jenkins/workspace/BuildToolchainAARCH64_GCC10/toolchain/gits/glibc/csu/../sysdeps/aarch64/start.S:95