1:代码
下面是一个简单的能够发生死锁的代码:
#include <unistd.h>
#include <pthread.h>
#include <string.h>
typedef struct
{
pthread_mutex_t mutex1;
pthread_mutex_t mutex2;
int sequence1;
int sequence2;
}Counter;
void* thread1(void* arg)
{
Counter *cc = (Counter *)arg;
while (1)
{
pthread_mutex_lock(&cc->mutex1);
++cc->sequence1;
sleep(1);
pthread_mutex_lock(&cc->mutex2);
++cc->sequence2;
pthread_mutex_unlock(&cc->mutex2);
pthread_mutex_unlock(&cc->mutex1);
}
}
void* thread2(void* arg)
{
Counter *cc = (Counter *)arg;
while (1)
{
pthread_mutex_lock(&cc->mutex2);
++cc->sequence2;
sleep(1);
pthread_mutex_lock(&cc->mutex1);
++cc->sequence1;
pthread_mutex_unlock(&cc->mutex1);
pthread_mutex_unlock(&cc->mutex2);
}
}
int main()
{
Counter pub_counter = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0, 0};
pthread_t tid[2];
if (pthread_create(&tid[0], NULL, &thread1, &pub_counter) != 0)
{
_exit(1);
}
if (pthread_create(&tid[1], NULL, &thread2, &pub_counter) != 0)
{
_exit(1);
}
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
return 0;
}
2:编译运行
编译时加上-g选项,以便能够得到符号对应的源码
gcc -o deadlock -g deadlock.c -pthread
./deadlock
3:pstack查看调用栈
使用pstack命令,可以查看正在运行的进程的调用栈:
# ps -ef|grep deadlock
root 9867 9032 0 14:13 pts/7 00:00:00 ./deadlock
root 9956 8991 0 14:16 pts/5 00:00:00 grep --color=auto deadlock
# pstack 9867
Thread 3 (Thread 0x7f6093bf6700 (LWP 9868)):
#0 0x00007f6093fc61bd in __lll_lock_wait () from /lib64/libpthread.so.0
#1 0x00007f6093fc1d02 in _L_lock_791 () from /lib64/libpthread.so.0
#2 0x00007f6093fc1c08 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3 0x00000000004007d8 in thread1 (arg=0x7fffad4cbeb0) at deadlock.c:26
#4 0x00007f6093fbfdc5 in start_thread () from /lib64/libpthread.so.0
#5 0x00007f6093cee76d in clone () from /lib64/libc.so.6
Thread 2 (Thread 0x7f60933f5700 (LWP 9869)):
#0 0x00007f6093fc61bd in __lll_lock_wait () from /lib64/libpthread.so.0
#1 0x00007f6093fc1d02 in _L_lock_791 () from /lib64/libpthread.so.0
#2 0x00007f6093fc1c08 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3 0x0000000000400852 in thread2 (arg=0x7fffad4cbeb0) at deadlock.c:44
#4 0x00007f6093fbfdc5 in start_thread () from /lib64/libpthread.so.0
#5 0x00007f6093cee76d in clone () from /lib64/libc.so.6
Thread 1 (Thread 0x7f60943e1740 (LWP 9867)):
#0 0x00007f6093fc0ef7 in pthread_join () from /lib64/libpthread.so.0
#1 0x0000000000400908 in main () at deadlock.c:66
多运行几次,发现每次的打印中,线程2和3都卡在__lll_lock_wait函数中,这就是一个明显的死锁发生的信号了。
4:gdb
4.1 attach到进程
使用gdb命令,attach到进程上,查看锁的状态:
# gdb attach 9867
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-94.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
attach: No such file or directory.
Attaching to process 9867
Reading symbols from /root/devel/mycode/deadlock...done.
Reading symbols from /lib64/libpthread.so.0...(no debugging symbols found)...done.
[New LWP 9869]
[New LWP 9868]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Loaded symbols for /lib64/libpthread.so.0
Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x00007f6093fc0ef7 in pthread_join () from /lib64/libpthread.so.0
Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7_3.4.x86_64
4.2查看改进程当前有哪些线程:
(gdb) info thread
Id Target Id Frame
3 Thread 0x7f6093bf6700 (LWP 9868) "deadlock" 0x00007f6093fc61bd in __lll_lock_wait () from /lib64/libpthread.so.0
2 Thread 0x7f60933f5700 (LWP 9869) "deadlock" 0x00007f6093fc61bd in __lll_lock_wait () from /lib64/libpthread.so.0
* 1 Thread 0x7f60943e1740 (LWP 9867) "deadlock" 0x00007f6093fc0ef7 in pthread_join () from /lib64/libpthread.so.0
*说明当前正在线程1上,需要切换到线程2和线程3上,查看锁的状态。
先切换到线程2上,并打印调用栈:
(gdb) thread 2
[Switching to thread 2 (Thread 0x7f60933f5700 (LWP 9869))]
#0 0x00007f6093fc61bd in __lll_lock_wait () from /lib64/libpthread.so.0
(gdb) bt
#0 0x00007f6093fc61bd in __lll_lock_wait () from /lib64/libpthread.so.0
#1 0x00007f6093fc1d02 in _L_lock_791 () from /lib64/libpthread.so.0
#2 0x00007f6093fc1c08 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3 0x0000000000400852 in thread2 (arg=0x7fffad4cbeb0) at deadlock.c:44
#4 0x00007f6093fbfdc5 in start_thread () from /lib64/libpthread.so.0
#5 0x00007f6093cee76d in clone () from /lib64/libc.so.6
线程2的”PID”为9869。调用栈显示该线程正阻塞在pthread_mutex_lock上。尝试看一下锁的状态:
(gdb) p cc
No symbol "cc" in current context.
(gdb) frame 3
#3 0x0000000000400852 in thread2 (arg=0x7fffad4cbeb0) at deadlock.c:44
44 pthread_mutex_lock(&cc->mutex1);
(gdb) p cc
$1 = (Counter *) 0x7fffad4cbeb0
(gdb) p cc->mutex1
$2 = {__data = {__lock = 2, __count = 0, __owner = 9868, __nusers = 1, __kind = 0, __spins = 0, __list = {__prev = 0x0,
__next = 0x0}}, __size = "