通常在程序挂掉的时候我们会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. linux下ioctl遇到的坑

    在驱动编程里面经常会用到ioctl的系统调用,发现cmd = 2的时候,用户ioctl直接返回-1. 原因在于在linux-x.xx/fs/ioctl.c定义的do_vfs_ioctl函数 int d ...

  2. /etc/ntp.conf

    摘录一: System:ubuntu10.04 配置文件路径:/etc/ntp.conf   配置格式:关键字(如server)    参数(如prefer) 以换行为结束,所以一个配置不能占多行. ...

  3. virtualvm一次插件安装想到的

    在麒麟操作系统visualvm安装插件失败,因为使用的内网,所以在官网下载了插件到本地:因为本地安装的jdk1.6,为了享受jdk1.8,在visualvm文件中增加了对于jdk1.8的引用: exp ...

  4. PyCharm 2017.2.2+PyQt5+Python3.6.0

    PyCharm注册地址 http://idea.imsxm.com/ 安装的是miniconda激活虚拟环境执行pip install PyQt5pip install PyQt5-tools 从官网 ...

  5. java代码继承难点。构造方法的调用

    总结:子类默认调用父类的无参构造方法.重写时,父类方法将被覆盖,不被调用,在子类中可以使用super.方法():可以实现 运行显示: evente.x:55 evente.x:55 B.y:57 pa ...

  6. 关于64位操作系统使用C#访问注册表失败的问题

    通过C#的注册表类 Registry.GetValue 进行访问时,其返回值一直为空.然后认真检查检查再检查了注册表路径,发现路径没有一点问题,不说废话,上代码: if (Registry.GetVa ...

  7. MySQL 学习五 SQL实用函数

    0 select now() 显示当前时间. 1 select char_length('andyqan')   显示字符长度. 2 日期格式化         select date_format( ...

  8. 高效C#编码优化

    1.foreach VS for 语句 Foreach 要比for具有更好的执行效率Foreach的平均花费时间只有for的30%.通过测试结果在for和foreach都可以使用的情况下,我们推荐使用 ...

  9. 2014.12.22 几个有用的oracle正则表达式

    SELECT REGEXP_REPLACE('LSS12345', '[^0-9]') FROM DUAL 结果:12345 '[^0-9]'中的^表示‘非’上述表达式的含义是“将LSS12345中的 ...

  10. [Python Study Notes]一个简单的区块链结构(python 2.7)

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ...