通常在程序挂掉的时候我们会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. [MySQL-MM] 生产环境自动恢复MM中一台M2库的过程,分享从零开始写的自动化重建脚本以及思路 (转)

    必须是MM架构,而且一台主库M1是完好无损的,一台主库M2可以根据M1主库来进行重建:如果MS架构,自己可以稍微做一下脚本修改动作,也能使用,架构如下图所示: 3  总体思路,建立主脚本a_build ...

  2. springmvc 加载静态文件失败

    header.jsp,部分代码 <head> <title>QA|VIS_PLATFORM</title> <meta content="width ...

  3. Flash在线签名小程序,可回放,动态导出gif图片

    需求: 公司为了使得和客户领导签字的时候记录下来,签字过程,可以以后动态回放演示,最好是gif图片,在网页上也容易展示,文件也小. 解决过程: 始我们去寻找各种app,最终也没有找到合适的,后来我在f ...

  4. 以ed结尾的单词

    1 规则动词词尾加-ed有三种读音 1.1 以清辅音结尾,加-ed    在清辅音后读作[ t ].如:     ask     →  asked                  look   → ...

  5. [转]在 Windows 操作系统中的已知安全标识符(Sid security identifiers)

    安全标识符 (SID) 是用于标识安全主体或安全组在 Windows 操作系统中的可变长度的唯一值.常用 Sid 的 Sid 标识普通用户的一组或通用组.跨所有操作系统,它们的值保持不变. 此信息可用 ...

  6. 问题:oracle LISTAGG 连接字符串;结果:Oracle 连接字符串的方法

    Oracle 连接字符串的方法 方法一:wmsys.wm_concat(column) 介绍:其函数在Oracle 10g推出,在10g版本中,返回字符串类型,在11g版本中返回clob类型.括号里面 ...

  7. DHCP工作工程

    1.客户端请求IP 客户端发一个DHCP DISCOVEY(包含主机名.mac地址)广播包 2.服务端响应请求 DHCP服务器收到请求后,查看自己的地址池是否有合法的地址.如果有,广播一个DHCP o ...

  8. pow求一个数的n次幂

    #!/usr/bin/env python i = pow(2,5) #求一个数的n次幂 print(i) C:\Python35\python3.exe F:/Python/2day/c6.py 3 ...

  9. oracle 之sys 、system区别

    角色 1)最重要的区别,存储的数据的重要性不同sys--所有oracle的数据字典的基表和视图都存放在sys用户中,这些基表和视图对于oracle的运行是至关重要的,由数据库自己维护,任何用户都不能手 ...

  10. jquery获取元素在文档中的位置信息以及滚动条位置(转)

    jquery获取元素在文档中的位置信息以及滚动条位置 http://blog.csdn.net/qq_34095777/article/details/78750886     原文链接 原创 201 ...