多线程死锁调试小技巧
来源:互联网 发布:vb串口校验和 编辑:程序博客网 时间:2024/06/05 14:16
据说再高的高手在写多线程程序的时候都难确保不会产生死锁,死锁的调试也就成为一个比较常见的问题,假设有下面这样一个问题:
一个正在生产环境下运行的进程死锁了,或者你只是在跑一个程序,并没有在调试器里面打开它,然后发现没有响应,日志输出也停止了。由于你是一个有经验的程序员,会想到“我刚刚加上了新的锁策略,不一定稳定,这可能是死锁了“。但是你不想就这么杀掉进程,因为多线程的 bug 不容易重现,遇上一次死锁可能要凭运气,错过了这次,它下次死锁可能会出现在你演示给老板看的时候……怎么办?
对于这样的问题可以借助Core Dump来调试。
什么是Core Dump?
Core的意思是内存, Dump的意思是扔出来, 堆出来.开发和使用Unix程序时, 有时程序莫名其妙的down了, 却没有任何的提示(有时候会提示core dumped). 这时候可以查看一下有没有形如core.进程号的文件生成运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在一个core文件中, 叫core dump.这个文件便是操作系统把程序down掉时的内存内容扔出来生成的, 它可以做为调试程序的参考.
Core Dump又叫核心转储, 当程序没有core文件生成怎么办呢?
有时候程序down了, 但是core文件却没有生成,core文件的生成跟你当前系统的环境设置有关系, 可以用下面的语句设置一下, 然后再运行程序便会生成core文件.
ulimit -c unlimited
core文件生成的位置一般于运行程序的路径相同, 文件名一般为core.进程号,在我的ubuntu12.04lts下生产的文件名为core。
介绍了core dump之后,来看看如何在多线程调试中使用core dump。
使用 kill 命令产生 core dump文件:
kill -11 pid
这不还是杀掉进程嘛?没错,但是你用信号11杀掉它,会让进程产生一个 Segmentation Fault,从而(如果你没禁用 core dump 的话),导致一个 core dump。随后你得到一个 core 文件,里面包含了死锁的时候,进程的内存镜像,也就包括了正在纠结缠绵,生离死别从而产生死锁的那两个,没准是几个,线程们的,栈。
现在知道该怎么办了吧?用 gdb 打开这个 core 文件,然后
thread apply all bt
gdb 会打出所有线程的栈,如果你发现有那么几个栈停在 pthread_wait 或者类似调用上,大致就可以得出结论:就是它们几个儿女情长,耽误了整个进程。
下面我来举一个简单的例子
#include <stdio.h>#include <unistd.h>#include <pthread.h>pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;void *func_2(void *arg){ pthread_mutex_lock(&m2); printf("about to dead_lock\n");sleep(1); pthread_mutex_lock(&m1); pthread_exit(NULL);}void *func_1(void *arg){pthread_mutex_lock(&m1); sleep(1); pthread_mutex_lock(&m2);pthread_exit(NULL);}int main(){pthread_t tid1, tid2; pthread_create(&tid1, NULL, func_1, NULL); pthread_create(&tid2, NULL, func_2, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); return 0;}
编译代码
$> gcc -Wall dead_lock_demo.c -o dead_lock_demo -g -lpthread
运行程序,发现程序打印出“about to dead_lock” 就不动了,现在我们使用gdb来调试。注意gdb的版本要高于7.0,之前使用过gdb6.3调试多线程是不行的。
在这之前需要先产生core dump文件:
$> ps -aux | grep dead_lock_demo
找出 dead_lock_demo 线程号,然后:
$> kill -11 pid
此时会生成core dump 文件,在我的系统上名字就是 core
然后调试:
$> gdb dead_lock_demo core
$> thread apply all bt
下面来看一下实际的过程:
从上图可以看出两个线程都阻塞在wait上,而且还给出了在哪一行代码中,很容易就定位到产生死锁的位置。
- 多线程死锁调试小技巧
- 多线程死锁调试小技巧
- 多线程死锁调试小技巧
- 多线程死锁调试小技巧
- 多线程死锁调试小技巧
- 多线程死锁调试小技巧
- 多线程死锁调试小技巧
- c++ 多线程调试小技巧
- Windebug 调试多线程程序死锁
- 使用gdb调试多线程死锁
- GDB调试多线程及死锁
- gdb调试多线程出现的死锁
- 调试小技巧
- vc 调试小技巧
- VC调试小技巧
- 调试小技巧--define
- 代码调试小技巧
- 调试小技巧
- 数据统计分析的归一化问题
- 关于GDB调试go语言程序中出现 os.Args无法打印的问题
- WPF常用控件属性
- Android中处理崩溃异常
- poj 1328(贪心)
- 多线程死锁调试小技巧
- iOS 上传头像 裁剪
- 浩易南:成功和环境有关吗
- uva 11542 Square (高斯消元)
- 千术教程,千术揭秘,麻将技巧,扑克千术揭秘
- Python之函数
- OSCache源码阅读(一)
- 栈帧,局部变量表,操纵数栈()
- MBProgressHUD的基本使用