通常在程序挂掉的时候我们会catch 他们挂掉的signal,然后在signal中打印出当时的一个stack,来方便问题调查, 但是在stack overflow的情况发生时,会没有拿到stack。signal的stack也是建立在thread的调用栈上的,在overflow的情况下,stack没有足够的空间来执行signal处理函数,signal处理函数就会被忽略。


示例代码:
main 主程序

#include <signal.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include "mybacktrace.h" void recursiondeath()
{
  char buffer[];
  recursiondeath();
  memset(buffer, 0xeb, sizeof(buffer));
  printf("%d", buffer[]);
} void* threadloop(void* args)
{
  // using sginal stack
  char altstack[SIGSTKSZ];
  addsignalstack(altstack, SIGSTKSZ);   recursiondeath();
  return NULL;
} int main(int argc, char const *argv[])
{
  char altstack[SIGSTKSZ];
  registersignal();
  addsignalstack(altstack, SIGSTKSZ);   pthread_t t;
  pthread_create(&t, NULL, threadloop, NULL);   pthread_join(t, NULL);   return ;
}

mybacktrace.h 头文件

#include <execinfo.h>
#include <signal.h>
#include <assert.h> void signalhandler(int sig)
{
printf("signal revived [%d]\n", sig);
// get the back trace
enum {
MAX_STACK = ,
}; void *stack[MAX_STACK];
int size = backtrace(stack, MAX_STACK);
if(size == ) {
printf("fail to get backtrace\n");
}
char** strs = backtrace_symbols(stack, size);
int i = ;
for (i = ; i < size; ++i) {
printf("%s\n", strs[i]);
}
free(strs); signal(sig, SIG_DFL);
} void addsignalstack(char *stack, int size)
{
assert(stack!=NULL);
// using sginal stack
stack_t sigstack;
sigstack.ss_sp = stack;
sigstack.ss_size = SIGSTKSZ;
sigstack.ss_flags = ;
if (sigaltstack(&sigstack, ) < ) {
perror("sig stack setting failed");
}
} void registersignal()
{
struct sigaction act;
act.sa_handler = signalhandler;
act.sa_flags = SA_ONSTACK|SA_RESTART; int ret = sigaction(SIGSEGV, &act, NULL);
if (ret < ) {
perror("sigaction failed\n");
} ret = sigaction(SIGBUS, &act, NULL);
if (ret < ) {
perror("sigaction failed\n");
} ret = sigaction(SIGILL, &act, NULL);
if (ret < ) {
perror("sigaction failed\n");
} }

说明:
添加signal alt stack

void addsignalstack(char *stack, int size)
{
assert(stack!=NULL);
// using sginal stack
stack_t sigstack;
sigstack.ss_sp = stack;
sigstack.ss_size = SIGSTKSZ;
sigstack.ss_flags = ;
if (sigaltstack(&sigstack, ) < ) {
perror("sig stack setting failed");
}
}

这边由外部传进来的数组作为signal 处理函数执行用的stack
注册signal函数:
```

void registersignal()
{
  struct sigaction act;
  act.sa_handler = signalhandler;
  act.sa_flags = SA_ONSTACK|SA_RESTART;   int ret = sigaction(SIGSEGV, &act, NULL);
  if (ret < ) {
    perror("sigaction failed\n");
  }   ret = sigaction(SIGBUS, &act, NULL);
  if (ret < ) {
    perror("sigaction failed\n");
  }   ret = sigaction(SIGILL, &act, NULL);
  if (ret < ) {
    perror("sigaction failed\n");
  }
}

注册了signal
SIGSEGV
SIGBUS
SIGILL
另外sigaction flag添加了SA_ONSTACK,确保当signal发生的时候,
signal处理函数会将sig atl stack作为函数frame


主函数:

int main(int argc, char const *argv[])
{
char altstack[SIGSTKSZ];
registersignal();
addsignalstack(altstack, SIGSTKSZ); pthread_t t;
pthread_create(&t, NULL, threadloop, NULL); pthread_join(t, NULL); return ;
}

执行前添加下signal的altstak,这里使用栈上的数组来作为signal处理函数的函数栈,可以通过malloc或者mmap分配.


线程的主函数

void* threadloop(void* args)
{
// using sginal stack
char altstack[SIGSTKSZ];
addsignalstack(altstack, SIGSTKSZ); recursiondeath();
return NULL;
}

执行前再添加下sig alt stack
注意:sig alt stack时每个线程自己单独的属性,所以每个线程都需要添加自己的sig alt stack

pthread中如何追踪stack over flow的更多相关文章

  1. 转载~kxcfzyk:Linux C语言多线程库Pthread中条件变量的的正确用法逐步详解

    Linux C语言多线程库Pthread中条件变量的的正确用法逐步详解   多线程c语言linuxsemaphore条件变量 (本文的读者定位是了解Pthread常用多线程API和Pthread互斥锁 ...

  2. <s:property="a" value=""/>取的<s:debug></s:debug>中的value stack中的属性值

    <s:property="a"  value=""/>取的<s:debug></s:debug>中的value stack中 ...

  3. 操作系统中 heap 和 stack 的区别

    操作系统中 heap 和 stack 的区别heap 和 stack是什么堆栈是两种数据结构.堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除.==在单片机 ...

  4. 在onelogin中使用OpenId Connect Implicit Flow

    目录 简介 OpenId Implicit Flow 创建onelogin的配置 页面的运行和请求流程 关键代码 总结 简介 onelogin支持多种OpenId Connect的连接模式,上一篇文章 ...

  5. pthread中取消线程

    取消线程:告诉一个线程关掉自己,取消操作允许线程请求终止其所在进程中的任何其他线程.不希望或不需要对一组相关的线程执行进一步操作时,可以选择执行取消操作.取消线程的一个示例是异步生成取消条件. 对于c ...

  6. java中Set,Map,Stack一些简单用法

    import java.util.Iterator; import java.util.Stack; import java.io.*; import java.util.Set; import ja ...

  7. C#中泛型容器Stack<T>

    我以前都是学出c,c++,这个学期开始学c#有点不适应,在编程中遇到些问题,所以自己在网上查了些资料,翻了一下书,写一些总结. 关于c#中Stack<T>泛型容器: <1>st ...

  8. Knockoutjs官网翻译系列(四) computed中依赖追踪是如何工作的

    初学者无需了解这些 ,但是很多高级程序员想知道我们为什么可以保持跟踪这些依赖以及可以正确的更新到UI中.它其实很简单.跟踪算法是这样的: 无论何时你定义了一个computed observable,K ...

  9. 解释内存中的栈(stack)、堆(heap)和静态区(static area)的用法

    堆区:专门用来保存对象的实例(new 创建的对象和数组),实际上也只是保存对象实例的属性值,属性的类型和对象本身的类型标记等,并不保存对象的方法(方法是指令,保存在Stack中) 1.存储的全部是对象 ...

随机推荐

  1. redis 双写一致性问题

    首先,缓存由于其高并发和高性能的特性,已经在项目中被广泛使用.在读取缓存方面,大家没啥疑问,都是按照下图的流程来进行业务操作. 但是在更新缓存方面,对于更新完数据库,是更新缓存呢,还是删除缓存.又或者 ...

  2. 设置Qt应用程序图标及应用程序名 【转载】

    一直以来很纠结给qt应用程序添加图标问题,在网上收过一次,但是感觉不够完整,现将自己的实现过程记录下,以便以后查看: 通过网上的例子知道qt助手中有相关说明: Setting the Applicat ...

  3. bzoj 2744 [HEOI2012]朋友圈——补图!+匈牙利算法

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2744 求最大的团<==>补图(有边的变成没边.没边的变成有边)的最大独立集! A ...

  4. iOS 【资源篇】

    iOS9开发入门教程索引 Objective-C视频教程 O-c Blog 社区 畅游  http://www.9ria.com/ 苹果中文开发社区  http://www.cocoachina.co ...

  5. HDU1584(蜘蛛牌)

    蜘蛛牌 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  6. [转载]PCI/PCIe基础——配置空间

    转载地址:http://blog.csdn.net/jiangwei0512/article/details/51603525 PCI/PCIe设备有自己的独立地址空间,这部分空间会映射到整个系统的地 ...

  7. Day2-VIM(二):插入

    基础 字符位置插入 i 在光标之前插入 a 在光标之后追加 你看,其实刚开始用这两个就足够了,这就是最基础的 为什么这么说呢?因为你可以依靠上一节中的移动命令来达到任意位置,然后再大力插入 不要忘了, ...

  8. rtsp/rtp over http

    转载:http://linux-expert.blog.163.com/blog/static/764585292008530912712/ rtsp/rtp over http C->S (g ...

  9. MySQL/InnoDB tips & tricks

    本文讨论的是 MySQL 5.7. 1.混用 * 和列名会产生解析错误,要避免这个错误,要使用 tbl_name.* 的格式. 2.where 子句中不能使用 select 中定义的别名,因为 SQL ...

  10. MYSQL BENCHMARK()函数

    MySQL有一个内置的BENCHMARK()函数,可以测试某些特定操作的执行速度. BENCHMARK(count,expr) BENCHMARK会重复计算expr表达式count次,通过这种方式就可 ...