转载:

http://blog.chinaunix.net/uid-30343738-id-5757210.html

  1. #include <stdio.h>
  2. #include <pthread.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5.  
  6. static int sequence1 = ;
  7. static int sequence2 = ;
  8.  
  9. pthread_mutex_t lock1;
  10. pthread_mutex_t lock2;
  11.  
  12. int func1()
  13. {
  14. pthread_mutex_lock(&lock1);
  15. ++sequence1;
  16. sleep();
  17. pthread_mutex_lock(&lock2);
  18. ++sequence2;
  19. pthread_mutex_unlock(&lock2);
  20. pthread_mutex_unlock(&lock1);
  21.  
  22. return sequence1;
  23. }
  24.  
  25. int func2()
  26. {
  27. pthread_mutex_lock(&lock2);
  28. ++sequence2;
  29. sleep();
  30. pthread_mutex_lock(&lock1);
  31. ++sequence2;
  32. pthread_mutex_unlock(&lock1);
  33. pthread_mutex_unlock(&lock2);
  34.  
  35. return sequence1;
  36. }
  37.  
  38. void* thread1(void *arg)
  39. {
  40. int rev = ;
  41. while()
  42. {
  43. rev = func1();
  44.  
  45. if (rev == )
  46. {
  47. pthread_exit(NULL);
  48. }
  49. }
  50. }
  51.  
  52. void* thread2(void *arg)
  53. {
  54. int rev = ;
  55. while()
  56. {
  57. rev = func2();
  58.  
  59. if (rev == )
  60. {
  61. pthread_exit(NULL);
  62. }
  63. }
  64. }
  65.  
  66. void* thread3(void *arg)
  67. {
  68. int count = ;
  69. while()
  70. {
  71. sleep();
  72. if ( count++ > )
  73. {
  74. pthread_exit(NULL);
  75. }
  76. }
  77. }
  78.  
  79. void* thread4(void *arg)
  80. {
  81. int count = ;
  82. while()
  83. {
  84. sleep();
  85. if ( count++ > )
  86. {
  87. pthread_exit(NULL);
  88. }
  89. }
  90. }
  91.  
  92. int main()
  93. {
  94. pthread_t tid[];
  95.  
  96. pthread_mutex_init(&lock1, NULL);
  97.  
  98. pthread_mutex_init(&lock2, NULL);
  99.  
  100. if(pthread_create(&tid[], NULL, &thread1, NULL) != )
  101. {
  102. _exit();
  103. }
  104.  
  105. if(pthread_create(&tid[], NULL, &thread2, NULL) != )
  106. {
  107. _exit();
  108. }
  109.  
  110. if(pthread_create(&tid[], NULL, &thread3, NULL) != )
  111. {
  112. _exit();
  113. }
  114.  
  115. if(pthread_create(&tid[], NULL, &thread4, NULL) != )
  116. {
  117. _exit();
  118. }
  119.  
  120. sleep();
  121.  
  122. pthread_join(tid[], NULL);
  123. pthread_join(tid[], NULL);
  124. pthread_join(tid[], NULL);
  125. pthread_join(tid[], NULL);
  126.  
  127. pthread_mutex_destroy( &lock1 );
  128. pthread_mutex_destroy( &lock2 );
  129.  
  130. return ;
  131. }

编译执行程序。

gcc -o main main17.c -lpthread -g

使用 pstack 和 gdb 工具对死锁程序进行分析

1、使用pstack

查找测试程序的进程号

root 5383 1 0 06:31 ? 00:00:43 gedit /root/Project/xa/main17.c
root 7197 7179 0 10:04 pts/1 00:00:00 ./main
root 7218 7206 0 10:04 pts/2 00:00:00 grep --color=auto main

对死锁进程第一次执行 pstack(pstack –进程号)的输出结果

  1. Thread 5 (Thread 0x41e37940 (LWP 6722)):
  2. #0 0x0000003d1a80d4c4 in __lll_lock_wait () from /lib64/libpthread.so.0
  3. #1 0x0000003d1a808e1a in _L_lock_1034 () from /lib64/libpthread.so.0
  4. #2 0x0000003d1a808cdc in pthread_mutex_lock () from /lib64/libpthread.so.0
  5. #3 0x0000000000400a9b in func1() ()
  6. #4 0x0000000000400ad7 in thread1(void*) ()
  7. #5 0x0000003d1a80673d in start_thread () from /lib64/libpthread.so.0
  8. #6 0x0000003d19cd40cd in clone () from /lib64/libc.so.6
  9. Thread 4 (Thread 0x42838940 (LWP 6723)):
  10. #0 0x0000003d1a80d4c4 in __lll_lock_wait () from /lib64/libpthread.so.0
  11. #1 0x0000003d1a808e1a in _L_lock_1034 () from /lib64/libpthread.so.0
  12. #2 0x0000003d1a808cdc in pthread_mutex_lock () from /lib64/libpthread.so.0
  13. #3 0x0000000000400a17 in func2() ()
  14. #4 0x0000000000400a53 in thread2(void*) ()
  15. #5 0x0000003d1a80673d in start_thread () from /lib64/libpthread.so.0
  16. #6 0x0000003d19cd40cd in clone () from /lib64/libc.so.6
  17. Thread 3 (Thread 0x43239940 (LWP 6724)):
  18. #0 0x0000003d19c9a541 in nanosleep () from /lib64/libc.so.6
  19. #1 0x0000003d19c9a364 in sleep () from /lib64/libc.so.6
  20. #2 0x00000000004009bc in thread3(void*) ()
  21. #3 0x0000003d1a80673d in start_thread () from /lib64/libpthread.so.0
  22. #4 0x0000003d19cd40cd in clone () from /lib64/libc.so.6
  23. Thread 2 (Thread 0x43c3a940 (LWP 6725)):
  24. #0 0x0000003d19c9a541 in nanosleep () from /lib64/libc.so.6
  25. #1 0x0000003d19c9a364 in sleep () from /lib64/libc.so.6
  26. #2 0x0000000000400976 in thread4(void*) ()
  27. #3 0x0000003d1a80673d in start_thread () from /lib64/libpthread.so.0
  28. #4 0x0000003d19cd40cd in clone () from /lib64/libc.so.6
  29. Thread 1 (Thread 0x2b984ecabd90 (LWP 6721)):
  30. #0 0x0000003d1a807b35 in pthread_join () from /lib64/libpthread.so.0
  31. #1 0x0000000000400900 in main ()

对死锁进程第二次执行 pstack(pstack –进程号)的输出结果

  1. Thread 5 (Thread 0x40bd6940 (LWP 6722)):
  2. #0 0x0000003d1a80d4c4 in __lll_lock_wait () from /lib64/libpthread.so.0
  3. #1 0x0000003d1a808e1a in _L_lock_1034 () from /lib64/libpthread.so.0
  4. #2 0x0000003d1a808cdc in pthread_mutex_lock () from /lib64/libpthread.so.0
  5. #3 0x0000000000400a87 in func1() ()
  6. #4 0x0000000000400ac3 in thread1(void*) ()
  7. #5 0x0000003d1a80673d in start_thread () from /lib64/libpthread.so.0
  8. #6 0x0000003d19cd40cd in clone () from /lib64/libc.so.6
  9. Thread 4 (Thread 0x415d7940 (LWP 6723)):
  10. #0 0x0000003d1a80d4c4 in __lll_lock_wait () from /lib64/libpthread.so.0
  11. #1 0x0000003d1a808e1a in _L_lock_1034 () from /lib64/libpthread.so.0
  12. #2 0x0000003d1a808cdc in pthread_mutex_lock () from /lib64/libpthread.so.0
  13. #3 0x0000000000400a03 in func2() ()
  14. #4 0x0000000000400a3f in thread2(void*) ()
  15. #5 0x0000003d1a80673d in start_thread () from /lib64/libpthread.so.0
  16. #6 0x0000003d19cd40cd in clone () from /lib64/libc.so.6
  17. Thread 3 (Thread 0x41fd8940 (LWP 6724)):
  18. #0 0x0000003d19c7aec2 in memset () from /lib64/libc.so.6
  19. #1 0x00000000004009be in thread3(void*) ()
  20. #2 0x0000003d1a80673d in start_thread () from /lib64/libpthread.so.0
  21. #3 0x0000003d19cd40cd in clone () from /lib64/libc.so.6
  22. Thread 2 (Thread 0x429d9940 (LWP 6725)):
  23. #0 0x0000003d19c7ae0d in memset () from /lib64/libc.so.6
  24. #1 0x0000000000400982 in thread4(void*) ()
  25. #2 0x0000003d1a80673d in start_thread () from /lib64/libpthread.so.0
  26. #3 0x0000003d19cd40cd in clone () from /lib64/libc.so.6
  27. Thread 1 (Thread 0x2af906fd9d90 (LWP 6721)):
  28. #0 0x0000003d1a807b35 in pthread_join () from /lib64/libpthread.so.0
  29. #1 0x0000000000400900 in main ()

连续多次查看这个进程的函数调用关系堆栈进行分析:当进程吊死时,多次使用 pstack 查看进程的函数调用堆栈,死锁线程将一直处于等锁的状态,对比多次的函数调用堆栈输出结果,

确定哪两个线程(或者几个线程)一直没有变化且一直处于等锁的状态(可能存在两个线程 一直没有变化)。

输出分析:

根据上面的输出对比可以发现,线程 1 和线程 2 由第一次 pstack 输出的处在 sleep 函数变化为第二次 pstack 输出的处在 memset 函数。但是线程 4 和线程 5 一直处在等锁状态(pthread_mutex_lock),

在连续两次的 pstack 信息输出中没有变化,所以我们可以推测线程 4 和线程 5 发生了死锁

2、使用gdb进行进一步的分析

查找测试程序的进程号

root 5383 1 0 06:31 ? 00:00:43 gedit /root/Project/xa/main17.c
root 7197 7179 0 10:04 pts/1 00:00:00 ./main
root 7218 7206 0 10:04 pts/2 00:00:00 grep --color=auto main

使用gdb 的attach功能

gdb attach 7197

查看当前进程的线程信息

(gdb) info thread
Id Target Id Frame
5 Thread 0xb7539b40 (LWP ) "main" 0xb7717424 in __kernel_vsyscall ()
4 Thread 0xb6d38b40 (LWP ) "main" 0xb7717424 in __kernel_vsyscall ()
3 Thread 0xb6537b40 (LWP ) "main" 0xb7717424 in __kernel_vsyscall ()
2 Thread 0xb5d36b40 (LWP ) "main" 0xb7717424 in __kernel_vsyscall ()
* 1 Thread 0xb753a6c0 (LWP ) "main" 0xb7717424 in __kernel_vsyscall ()

切换到线程 5 的输出

(gdb) thread  5
[Switching to thread 5 (Thread 0xb7539b40 (LWP 7198))]
#0 0xb7717424 in __kernel_vsyscall ()
(gdb) where
#0 0xb7717424 in __kernel_vsyscall ()
#1 0xb76f25a2 in __lll_lock_wait () from /lib/i386-linux-gnu/libpthread.so.0
#2 0xb76edead in _L_lock_686 () from /lib/i386-linux-gnu/libpthread.so.0
#3 0xb76edcf3 in pthread_mutex_lock ()
from /lib/i386-linux-gnu/libpthread.so.0
#4 0x0804864b in func1 () at main17.c:17
#5 0x080486ef in thread1 (arg=0x0) at main17.c:44
#6 0xb76ebd4c in start_thread () from /lib/i386-linux-gnu/libpthread.so.0
#7 0xb762adde in clone () from /lib/i386-linux-gnu/libc.so.6
(gdb) f  4
#4 0x0804864b in func1 () at main17.c:17
warning: Source file is more recent than executable.
17 pthread_mutex_lock(&lock2);     ////线程 5 正试图获得锁 lock2

切换到线程4的输出

(gdb) thread 4
[Switching to thread 4 (Thread 0xb6d38b40 (LWP 7199))]
#0 0xb7717424 in __kernel_vsyscall ()
(gdb) where
#0 0xb7717424 in __kernel_vsyscall ()
#1 0xb76f25a2 in __lll_lock_wait () from /lib/i386-linux-gnu/libpthread.so.0
#2 0xb76edead in _L_lock_686 () from /lib/i386-linux-gnu/libpthread.so.0
#3 0xb76edcf3 in pthread_mutex_lock ()
from /lib/i386-linux-gnu/libpthread.so.0
#4 0x080486ae in func2 () at main17.c:30
#5 0x0804871c in thread2 (arg=0x0) at main17.c:58
#6 0xb76ebd4c in start_thread () from /lib/i386-linux-gnu/libpthread.so.0
#7 0xb762adde in clone () from /lib/i386-linux-gnu/libc.so.6
(gdb) f 4
#4 0x080486ae in func2 () at main17.c:30
30 pthread_mutex_lock(&lock1);      //线程 4 正试图获得锁 lock1

打印锁的信息

(gdb) p lock1
$1 = {__data = {__lock = 2, __count = 0, __owner = , __kind = 0,
__nusers = 1, {__spins = 0, __list = {__next = 0x0}}},
__size = "\002\000\000\000\000\000\000\000\036\034\000\000\000\000\000\000\001\000\000\000\000\000\000", __align = 2}
(gdb) p lock2
$2 = {__data = {__lock = 2, __count = 0, __owner = , __kind = 0,
__nusers = 1, {__spins = 0, __list = {__next = 0x0}}},
__size = "\002\000\000\000\000\000\000\000\037\034\000\000\000\000\000\000\001\000\000\000\000\000\000", __align = 2}

从上面可以发现,线程 4 正试图获得锁 lock1,但是锁 lock1已经被 LWP 为 7198的线程得到(__owner = 7198),

线程 5 正试图获得锁 lock2,但是锁 lock2 已经被 LWP 为 7199的 得到(__owner = 7199),从 pstack 的输出可以发现(gdb info thread),LWP 7198与线程 5 是对应的,LWP 7199与线程 4 是对应的。

所以我们可以得出, 线程 4 和线程 5 发生了交叉持锁的死锁现象。查看线程的源代码发现,线程 4 和线程 5 同时使用 mutex1 和 mutex2,且申请顺序不合理

gdb调试分析多线程死锁的更多相关文章

  1. gdb常用命令及使用gdb调试多进程多线程程序

    一.常用普通调试命令 1.简单介绍GDB 介绍: gdb是Linux环境下的代码调试⼯具.使⽤:需要在源代码⽣成的时候加上 -g 选项.开始使⽤: gdb binFile退出: ctrl + d 或 ...

  2. 用gdb调试python多线程代码-记一次死锁的发现

    | 版权:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接.如有问题,可以邮件:wangxu198709@gmail.com 前言 相信很多人都有 ...

  3. gdb调试多进程多线程程序

    一.调试的指令 1.list命令 list linenum 显示程序第linenum行的周围的程序 list function 显示程序名为function的函数的源程序 list 显示当前行后面的源 ...

  4. 通过gdb调试分析Linux内核的启动过程

    作者:吴乐 山东师范大学 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.实验流程 1.打开环境 执 ...

  5. GDB调试汇编分析

    GDB调试汇编分析 代码 本次实践我参照了许多先做了的同学的博客,有卢肖明,高其,张梓靖同学.代码借用的是卢肖明同学的代码进行调试运行. GCC编译 使用gcc -g gdbtest.c -o gdb ...

  6. 20145233 GDB调试汇编分析

    GDB调试汇编分析 代码 #include<stdio.h> short addend1 = 1; static int addend2 = 2; const static long ad ...

  7. 20145219 gdb调试汇编堆栈分析

    20145219 gdb调试汇编堆栈分析 代码gdbdemo.c int g(int x) { return x+19; } int f(int x) { return g(x); } int mai ...

  8. 20145310 GDB调试汇编堆栈分析

    GDB调试汇编堆栈分析 由于老师说要逐条分析汇编代码,所以我学习卢肖明同学的方法,重新写了一篇博客. 代码: #include<stdio.h> short addend1 = 1; st ...

  9. gdb调试汇编堆栈过程的学习

    gdb调试汇编堆栈过程的学习 以下为C源文件 使用gcc - g code.c -o code -m32指令在64位的机器上产生32位汇编,然后使用gdb example指令进入gdb调试器: 进入之 ...

随机推荐

  1. 02: 安装epel 解决centos7无法使用yum安装nginx

    参考网址: http://www.mamicode.com/info-detail-1671603.html 1.yum命令安装 yum install epel-release -y 2.更新数据 ...

  2. 20165211 预备作业3 Linux安装与学习

    20165211 预备作业3 Linux安装与学习 1. Linux安装 涉及软件:VirtualBox,Ubuntu 参考教程:基于VirtualBox安装Ubuntu图文教程 安装过程的问题 在安 ...

  3. JS引擎深入分析

    转载自阮一峰:http://javascript.ruanyifeng.com/bom/engine.html 目录 JavaScript代码嵌入网页的方法 script标签:代码嵌入网页 scrip ...

  4. Python3基础 str find+index 是否存在指定字符串,有则返回第一个索引值

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  5. aws相关文档

    使用 IAM 角色授予对 Amazon EC2 上的 AWS 资源的访问权 https://docs.aws.amazon.com/zh_cn/sdk-for-java/v1/developer-gu ...

  6. 联想笔记本thinkpad按F2不能直接重命名

    联想笔记本thinkpad按F2不能直接重命名,而是Fn+F2. 解决: 按一下Fn+Esc(一般在左上角)

  7. PHP生成缩略图的一个方法类(转)

    //使用如下类就可以生成图片缩略图 class resizeimage { //图片类型 var $type; //实际宽度 var $width; //实际高度 var $height; //改变后 ...

  8. Windows系统下在Eclipse中集成Python

    我现在偶尔开发代码,已经不用Eclipse了,主要原因是查看Jar包中的代码反编译十分不便,项目加载的时候卡,偶尔还会崩溃 用Intellij IDEA和PyCharm 原来的笔记如何在Eclipse ...

  9. pandas.read_csv参数整理

    读取CSV(逗号分隔)文件到DataFrame,也支持文件的部分导入和选择迭代 更多帮助参见:http://pandas.pydata.org/pandas-docs/stable/io.html 参 ...

  10. pandas (loc、iloc、ix)的区别

    loc:通过行标签索引数据 iloc:通过行号索引行数据 ix:通过行标签或行号索引数据(基于loc和iloc的混合) 使用loc.iloc.ix索引第一行数据: loc: iloc: ix: