一般察看函数运行时堆栈的方法是使用GDB(bt命令)之类的外部调试器,但是,有些时候为了分析程序的BUG,(主要针对长时间运行程序的分析),在程序出错时打印出函数的调用堆栈是非常有用的。

在glibc头文件"execinfo.h"中声明了三个函数用于获取当前线程的函数调用堆栈。

int backtrace(void **buffer,int size)

/*judge whether process is exist*/
bool processExists(char * process_name) {
FILE *ptr;
int RE_BUF_SIZE = 32;
char rebuff[RE_BUF_SIZE];
char ps[128];
snprintf(ps, sizeof(ps), "ps | grep %s |grep -v grep| wc -l", process_name);
if((ptr = popen(ps, "r")) != NULL) {
int count = 0;
fgets(rebuff, RE_BUF_SIZE, ptr);
if(rebuff != NULL) {
count = atoi(rebuff);
}
pclose(ptr);
return count >= 1;
}

printf("Current process %s is not Exist!!!!\n",process_name);
return false;
}

static char *signal_str[] = {
[1] = "SIGHUP", [2] = "SIGINT", [3] = "SIGQUIT", [4] = "SIGILL", [5] = "SIGTRAP",
[6] = "SIGABRT", [7] = "SIGBUS", [8] = "SIGFPE", [9] = "SIGKILL", [10] = "SIGUSR1",
[11] = "SIGSEGV", [12] = "SIGUSR2", [13] = "SIGPIPE", [14] = "SIGALRM", [15] = "SIGTERM",
[16] = "SIGSTKFLT", [17] = "SIGCHLD", [18] = "SIGCONT", [19] = "SIGSTOP", [20] = "SIGTSTP",
[21] = "SIGTTIN", [22] = "SIGTTOU", [23] = "SIGURG", [24] = "SIGXCPU", [25] = "SIGXFSZ",
[26] = "SIGVTALRM", [27] = "SIGPROF", [28] = "SIGWINCH", [29] = "SIGIO", [30] = "SIGPWR",
[31] = "SIGSYS", [34] = "SIGRTMIN", [35] = "SIGRTMIN+1", [36] = "SIGRTMIN+2", [37] = "SIGRTMIN+3",
[38] = "SIGRTMIN+4", [39] = "SIGRTMIN+5", [40] = "SIGRTMIN+6", [41] = "SIGRTMIN+7", [42] = "SIGRTMIN+8",
[43] = "SIGRTMIN+9", [44] = "SIGRTMIN+10", [45] = "SIGRTMIN+11", [46] = "SIGRTMIN+12", [47] = "SIGRTMIN+13",
[48] = "SIGRTMIN+14", [49] = "SIGRTMIN+15", [50] = "SIGRTMAX-14", [51] = "SIGRTMAX-13", [52] = "SIGRTMAX-12",
[53] = "SIGRTMAX-11", [54] = "SIGRTMAX-10", [55] = "SIGRTMAX-9", [56] = "SIGRTMAX-8", [57] = "SIGRTMAX-7",
[58] = "SIGRTMAX-6", [59] = "SIGRTMAX-5", [60] = "SIGRTMAX-4", [61] = "SIGRTMAX-3", [62] = "SIGRTMAX-2",
[63] = "SIGRTMAX-1", [64] = "SIGRTMAX",
};

void sig_handler(int signo)
{
char cmd[64] = {};
void *array[10];
int size = 0;
char **strings = NULL;
int i = 0;

#if 0
printf("\n\n[%s: %d] bitbox crashed by signal %s.\n", __func__, __LINE__, signal_str[signo]);

printf("Call Trace:\n");
size = backtrace(array, 10);
strings = backtrace_symbols(array, size);
if (strings) {
for (i = 0; i < size; i++)
printf (" %s\n", strings[i]);
free (strings);
} else {
printf("Not Found\n\n");
}

if (signo == SIGSEGV || signo == SIGBUS ||
signo == SIGTRAP || signo == SIGABRT) {
sprintf(cmd, "cat /proc/%d/maps", getpid());
printf("Process maps:\n");
system(cmd);
}
#else
wdt_stop_count();
#endif

exit(-1);
}

int main(int argc, char **argv)
{
int c = -1;
int daemonize = 0;
printf("watchdog V1.7 start!!!!@_@\n");

signal(SIGPIPE, SIG_IGN);
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);
signal(SIGBUS, sig_handler);
signal(SIGSEGV, sig_handler);
signal(SIGABRT, sig_handler);

while (1) {
c = getopt(argc, argv, "bBf:h");
if (c < 0)
break;
switch (c) {
case 'b':
case 'B':
daemonize = 1;
break;
case 'f':
break;
case 'h':

return 0;
default:
return -1;
}
}

/* run in the background */
if (daemonize) {
if (daemon(0, 1)) {
perror("daemon");
return -1;
}
}

}

使用linux backtrace打印出错函数堆栈信息的更多相关文章

  1. Slf4j打印异常的堆栈信息

    一.前言 直接用logger.info("异常信息为:"+e)或者logger.info(e.getMessage())只能记录到异常的描述信息,却没有其异常具体发生在哪一行代码. ...

  2. 利用Xposed Hook打印Java函数调用堆栈信息的几种方法

    本文博客链接:http://blog.csdn.net/QQ1084283172/article/details/79378374 在进行Android逆向分析的时候,经常需要进行动态调试栈回溯,查看 ...

  3. 打印Java异常堆栈信息

    背景 在开发Java应用程序的时候,遇到程序抛异常,我们通常会把抛异常时的运行时环境保存下来(写到日志文件或者在控制台中打印出来).这样方便后续定位问题. 需要记录的运行时环境包含两部分内容:抛异常时 ...

  4. 在java中捕获异常时,使用log4j打印出错误堆栈信息

    当java捕获到异常时,把详细的堆栈信息打印出来有助于我们排查异常原因,并修复相关bug,比如下面两张图,是打印未打印堆栈信息和打印堆栈信息的对比: 那么在使用log4j输出日志时,使用org.apa ...

  5. Linux记录-jstack采集namenode堆栈信息

    #!/bin/bash #以hdfs用户执行jstack每分钟采集一次namenode heapstack日志 #mkdir -p /tmp/jstack export JAVA_HOME=/app/ ...

  6. Linux 如何使用gdb 查看core堆栈信息

    转载:http://blog.csdn.net/mergerly/article/details/41994207 core dump 一般是在segmentation fault(段错误)的情况下产 ...

  7. Logger.error方法之打印错误异常的详细堆栈信息

    一.问题场景 使用Logger.error方法时只能打印出异常类型,无法打印出详细的堆栈信息,使得定位问题变得困难和不方便. 二.先放出结论 Logger类下有多个不同的error方法,根据传入参数的 ...

  8. log4j打印错误异常的详细堆栈信息

    一.问题场景 使用Logger.error方法时只能打印出异常类型,无法打印出详细的堆栈信息,使得定位问题变得困难和不方便. 二.先放出结论 Logger类下有多个不同的error方法,根据传入参数的 ...

  9. Java内存泄漏分析系列之一:使用jstack定位线程堆栈信息

    原文地址:http://www.javatang.com 前一段时间上线的系统升级之后,出现了严重的高CPU的问题,于是开始了一系列的优化处理之中,现在将这个过程做成一个系列的文章. 基本概念 在对J ...

随机推荐

  1. Shell从入门到精通进阶之四:流程控制

    流程控制是改变程序运行顺序的指令. 4.1 if语句 4.1.1 单分支 if 条件表达式; then 命令 fi 示例: #!/bin/bash N=10 if [ $N -gt 5 ]; then ...

  2. .Net Core 根据配置文件动态发布至服务器

    前言 一个软件的开发周期需要经历开发.测试.上线三个基本的阶段,同理我们在开发过程中会需要经常切换不同的运行环境..NetCore可以通过配置文件以及写入系统环境变量来自动识别站点的运行环境,保证了数 ...

  3. 详解mybatis配置文件

    在前面两篇文章中,大致与大家分享了基于Java的ORM框架,Mybatis基本架构和Mybatis实现CRUD的基本原理与流程,在本篇文章中,继续与大家分享Mybatis配置文件. 通过研究Mybat ...

  4. JavaScript 是如何工作的:JavaScript 的内存模型

    摘要: 从内存角度理解 let 和 const 的意义. 原文:JavaScript 是如何工作的:JavaScript 的内存模型 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 这 ...

  5. ASP.NET Core 部署IIS及 OFFSET 附近有语法错误解决

    今天自己开发了一个订机票的微信公众号,功能基本已经完成,然后想部署到服务器实际测试下.结果部署上去出现各种问题.先安装asp.net core模块,然后发现数据库并不像在开发时一样,执行ef的命令行语 ...

  6. 微信小程序 选择微信自带的地址 用户授权选择了拒绝

    // 选择微信自带地址 addAddr:function () { wx.chooseAddress({ success: function (res) { self.setData({ addrIn ...

  7. git创建分支并提交到远程分支

    来自:https://www.cnblogs.com/bluestorm/p/6252900.html 侵删 git branch(分支命令的使用http://hbiao68.iteye.com/bl ...

  8. Android串口通讯

    今天在整一个项目,需要利用串口通讯在网上看了好多人的帖子才稍微整出了一点头绪. 首先串口代码就是利用谷歌自己的api,将java代码放在java/android_serialport_api目录下,如 ...

  9. Python使用Plotly绘图工具,绘制甘特图

    今天来讲一下如何使用Python 的绘图工具Plotly来绘制甘特图的方法 甘特图大家应该了解熟悉,就是通过条形来显示项目的进度.时间安排等相关情况的. 我们今天来学习一下,如何使用ployly来绘制 ...

  10. Windows Management Instrumentation 服务卸载并重新创建

    SC delete Winmgmt sc create Winmgmt binPath= "C:\Windows\System32\svchost.exe -k netsvcs" ...