pthread中如何追踪stack over flow
通常在程序挂掉的时候我们会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的更多相关文章
- 转载~kxcfzyk:Linux C语言多线程库Pthread中条件变量的的正确用法逐步详解
Linux C语言多线程库Pthread中条件变量的的正确用法逐步详解 多线程c语言linuxsemaphore条件变量 (本文的读者定位是了解Pthread常用多线程API和Pthread互斥锁 ...
- <s:property="a" value=""/>取的<s:debug></s:debug>中的value stack中的属性值
<s:property="a" value=""/>取的<s:debug></s:debug>中的value stack中 ...
- 操作系统中 heap 和 stack 的区别
操作系统中 heap 和 stack 的区别heap 和 stack是什么堆栈是两种数据结构.堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除.==在单片机 ...
- 在onelogin中使用OpenId Connect Implicit Flow
目录 简介 OpenId Implicit Flow 创建onelogin的配置 页面的运行和请求流程 关键代码 总结 简介 onelogin支持多种OpenId Connect的连接模式,上一篇文章 ...
- pthread中取消线程
取消线程:告诉一个线程关掉自己,取消操作允许线程请求终止其所在进程中的任何其他线程.不希望或不需要对一组相关的线程执行进一步操作时,可以选择执行取消操作.取消线程的一个示例是异步生成取消条件. 对于c ...
- java中Set,Map,Stack一些简单用法
import java.util.Iterator; import java.util.Stack; import java.io.*; import java.util.Set; import ja ...
- C#中泛型容器Stack<T>
我以前都是学出c,c++,这个学期开始学c#有点不适应,在编程中遇到些问题,所以自己在网上查了些资料,翻了一下书,写一些总结. 关于c#中Stack<T>泛型容器: <1>st ...
- Knockoutjs官网翻译系列(四) computed中依赖追踪是如何工作的
初学者无需了解这些 ,但是很多高级程序员想知道我们为什么可以保持跟踪这些依赖以及可以正确的更新到UI中.它其实很简单.跟踪算法是这样的: 无论何时你定义了一个computed observable,K ...
- 解释内存中的栈(stack)、堆(heap)和静态区(static area)的用法
堆区:专门用来保存对象的实例(new 创建的对象和数组),实际上也只是保存对象实例的属性值,属性的类型和对象本身的类型标记等,并不保存对象的方法(方法是指令,保存在Stack中) 1.存储的全部是对象 ...
随机推荐
- set/multiset容器
一.二叉树基本概念 二叉树就是任何节点最多只允许有两个子节点.分别是左子节点和右子节点. 二叉搜索树,是指二叉树中的节点按照一定的规则进行排序,使得对二叉树中元素访问更加高效.二叉搜索树的放置规则是: ...
- bzoj 4300 绝世好题——DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4300 考虑 dp[ i ] 能从哪些 j 转移过来,就是那些 a[ j ] & a[ ...
- winrm service
今天看脚本忽然发现一个服务,叫winRM服务,这是个PowerShell的远程管理.开启它可以很大程度的方便用PowerShell操控! 下面是我找到的一些资料: 在Linux中,我们可以使用安全的S ...
- 在CentOS上安装Java开发环境:使用yum安装jdk
请参考百度经验:http://jingyan.baidu.com/article/4853e1e51d0c101909f72607.html 如果您阅读过此文章有所收获,请为我顶一个,如果文章中有错误 ...
- 使用Spring Boot 和Spring Data JPA访问mysql数据库
在Spring中使用JdbcTemplate是一种基本的数据访问方式,但是仍然需要较多的代码,为了解决这些大量枯燥的数据操作语句,我们可以使用ORM框架,比如:Hibernate,通过整合Hibern ...
- Oracle 常见进程
1 服务器进程 专用服务器连接:数据连接跟服务器上的一个进程之间存在1:1的映射 共享服务器连接:多个会话共享一个服务器进程池,由一个调度程序分配 1.1 专用服务器连接 专用服务器连接模式下,客户连 ...
- 【OK210试用体验】进阶篇(1)视频图像采集之MJPG-streamer编译(Ubuntu系统下)
转自: http://bbs.elecfans.com/jishu_510084_1_1.html 本篇主要内容分为: 嵌入式视频图像开源库 mjpg-streamer简介 mjpg- ...
- Enable SVM while booted from alternate media (ZT)
http://www.seedsofgenius.net/uncategorized/solaris-tips-enable-svm-while-booted-from-alternate-media ...
- pl/sql使用部分整理
在工作中使用pl/sql工具,总结一下常用操作,以便以后复习,也希望帮助朋友们熟悉pl/sql操作! 1.pl/sql记住登录密码PL/SQL Developer->tools->Pref ...
- ROS探索总结(四)——简单的机器人仿真
前边我们已经介绍了ROS的基本情况,以及新手入门ROS的初级教程,现在就要真正的使用ROS进入机器人世界了.接下来我们涉及到的很多例程都是<ROS by Example>这本书的内容,我是 ...