使用 gdb 调试死锁线程

死锁调试预备

  • -g 参数
  • attach
  • info threads
  • thread + number 切换对应线程

testlock.cpp

  1 #include <iostream>
  2 #include <thread>
  3 #include <mutex>
  4 #include <unistd.h>
  5 
  6 std::mutex gMutex;
  7 
  8 void Test1()
  9 {   
 10     gMutex.lock();
 11     gMutex.lock();
 12 }
 13 
 14 void Test2()
 15 {   
 16     while (true) {
 17         sleep(1);
 18     }
 19 }
 20 
 21 int main()
 22 {   
 23     std::thread t1(Test1);
 24     std::thread t2(Test2);
 25     
 26     t1.join();
 27     t2.join();
 28     return 0;
 29 }

编译运行
编译:$ g++ -std=c++11 -g ./testlock.cpp -pthread
运行:$ ./a.out
程序挂起,然后使用 gdb 进行调试。

gdb 调试

# 查找进程 id
$ ps -ef |grep a.out
test 18951 18823  0 17:26 pts/7 00:00:00  ./a.out

# 使用 root 权限 进入 attach
$ gdb a.out 18951
(gdb) info threads
  Id   Target Id         Frame 
* 1    Thread 0x7f4545f6a740 (LWP 18951) "a.out" 0x00007f45455a798d in pthread_join (threadid=139935485835008, thread_return=0x0)
    at pthread_join.c:90
  2    Thread 0x7f4544ecb700 (LWP 18952) "a.out" __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
  3    Thread 0x7f45446ca700 (LWP 18953) "a.out" 0x00007f45452a130d in nanosleep () at ../sysdeps/unix/syscall-template.S:84

# 调到第二个线程
(gdb)t 2
[Switching to thread 2 (Thread 0x7f4544ecb700 (LWP 18952))]
#0  __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
135     ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: 没有那个文件或目录.

# 执行 bt
(gdb) bt
#0  __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
#1  0x00007f45455a8dbd in __GI___pthread_mutex_lock (mutex=0x6041a0 <gMutex>) at ../nptl/pthread_mutex_lock.c:80
#2  0x0000000000400e67 in __gthread_mutex_lock (__mutex=0x6041a0 <gMutex>) at /usr/include/x86_64-linux-gnu/c++/5/bits/gthr-default.h:748
#3  0x0000000000401224 in std::mutex::lock (this=0x6041a0 <gMutex>) at /usr/include/c++/5/mutex:135
#4  0x0000000000400f0f in Test1 () at ./testlock.cpp:11
#5  0x0000000000402525 in std::_Bind_simple<void (*())()>::_M_invoke<>(std::_Index_tuple<>) (this=0x1b77c48)
    at /usr/include/c++/5/functional:1531
#6  0x000000000040247e in std::_Bind_simple<void (*())()>::operator()() (this=0x1b77c48) at /usr/include/c++/5/functional:1520
#7  0x000000000040240e in std::thread::_Impl<std::_Bind_simple<void (*())()> >::_M_run() (this=0x1b77c30) at /usr/include/c++/5/thread:115
#8  0x00007f4545a8ac80 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#9  0x00007f45455a66ba in start_thread (arg=0x7f4544ecb700) at pthread_create.c:333
#10 0x00007f45452dc3dd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109

可以看到第 4 项 #4 0x0000000000400f0f in Test1 () at ./testlock.cpp:11 程序卡在了文件的 11 行。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 最近一直在看游双的《高性能linux服务器编程》一书,下载链接: http://download.csdn.net...
    张小方阅读 1,224评论 0 2
  • 调试前准备 获取进程的内核转储(core dump) why:最大好处是,其保存了问题发生时的状态。记录进程当前状...
    Gitlusen阅读 958评论 0 2
  • 什么是coredump Coredump叫做核心转储,它是进程运行时在突然崩溃的那一刻的一个内存快照。操作系统在程...
    java菜阅读 4,253评论 0 4
  • 大家好,接下来,我会为大家分享一本书叫——《非暴力沟通》。它的作者是美国马歇尔.卢森堡心理学博士。 这本书是我在今...
    一千樱花阅读 528评论 2 5
  • 伏在窗上的水气默默凝滴 挂在双颊上的泪滑落成雨 心的游魂在暗夜里飘来荡去 沉沉的午夜一片死寂 瘦弱的灯光赶走了睡意...
    光诗燃梦阅读 376评论 23 43