Linux GDB分析死鎖

目錄

示例代碼

分析

結論


示例代碼

// DeadLock.cpp : 定義控制檯應用程序的入口點。
//

#include <iostream>
#include <stdlib.h>
#include <thread>
#include <mutex>

static std::mutex mutex1;
static std::mutex mutex2;

static int threadFunc1()
{		
	std::cout << "Enter threadFunc1" << std::endl;
	std::lock_guard<std::mutex> lock1(mutex1);	
	std::this_thread::sleep_for(std::chrono::seconds(20));
	std::lock_guard<std::mutex> lock2(mutex2);
	std::cout << "Leave threadFunc1" << std::endl;	
	return 0;
}

static int threadFunc2()
{
	std::cout << "Enter threadFunc2" << std::endl;
	std::lock_guard<std::mutex> lock1(mutex2);		
	std::this_thread::sleep_for(std::chrono::seconds(20));	
	std::lock_guard<std::mutex> lock2(mutex1);
	std::cout << "Leave threadFunc2" << std::endl;	
	return 0;
}

int main()
{
	std::thread thread1(threadFunc1);
	std::thread thread2(threadFunc2);
	
	thread1.join();
	thread2.join();

	std::cout << "All thread end,now exit" << std::endl;	
    return 0;
}

編譯運行(目標程序爲testDemo):./testDemo

Enter threadFunc1

Enter threadFunc2

並未輸出:Leave threadFunc1 、 Leave threadFunc2、All thread end,now exit,隨後程序處於掛起狀態

分析

1、Gdb調試:gdb ./testDemo

2、 待到程序無反應時,通過Ctrl+C中斷程序運行

3、查看線程信息:info threads

Id   Target Id         Frame

* 1    Thread 0x7ffff7fdb740 (LWP 4315) "testDemo" 0x00007ffff7bbed2d in __GI___pthread_timedjoin_ex (threadid=140737335809792, thread_return=0x0,

    abstime=0x0, block=<optimized out>) at pthread_join_common.c:89

  2    Thread 0x7ffff6e85700 (LWP 4319) "testDemo" __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135

  3    Thread 0x7ffff6684700 (LWP 4320) "testDemo" __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135

我們看到,一共有三個線程,分別爲主線程,以及兩個子線程,線程號分別爲4319及4320。並且兩個子線程都處於鎖等待的狀態。

4、查看子線程4319堆棧信息:thread 2; bt(2 是相對線程號)

#0  __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135

#1  0x00007ffff7bc0023 in __GI___pthread_mutex_lock (mutex=0x5555557581a0 <mutex2>) at ../nptl/pthread_mutex_lock.c:78

#2  0x00005555555550bf in __gthread_mutex_lock (__mutex=0x5555557581a0 <mutex2>) at /usr/include/x86_64-linux-gnu/c++/7/bits/gthr-default.h:748

#3  0x0000555555555614 in std::mutex::lock (this=0x5555557581a0 <mutex2>) at /usr/include/c++/7/bits/std_mutex.h:103

#4  0x0000555555555690 in std::lock_guard<std::mutex>::lock_guard (this=0x7ffff6e84dc0, __m=...) at /usr/include/c++/7/bits/std_mutex.h:162

#5  0x0000555555555183 in threadFunc1 () at DeadLock.cpp:17

省略…..

子線程4319在等待mutex2

5、查看子線程4320堆棧信息:thread 3; bt(3 是相對線程號)

#0  __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135

#1  0x00007ffff7bc0023 in __GI___pthread_mutex_lock (mutex=0x555555758160 <mutex1>) at ../nptl/pthread_mutex_lock.c:78

#2  0x00005555555550bf in __gthread_mutex_lock (__mutex=0x555555758160 <mutex1>) at /usr/include/x86_64-linux-gnu/c++/7/bits/gthr-default.h:748

#3  0x0000555555555614 in std::mutex::lock (this=0x555555758160 <mutex1>) at /usr/include/c++/7/bits/std_mutex.h:103

#4  0x0000555555555690 in std::lock_guard<std::mutex>::lock_guard (this=0x7ffff6683dc0, __m=...) at /usr/include/c++/7/bits/std_mutex.h:162

#5  0x000055555555529e in threadFunc2 () at DeadLock.cpp:27

子線程4320在等待鎖mutex1

6、查看mutex1、mutex2的信息

p mutex1:

{

  <std::__mutex_base> = {

    _M_mutex = pthread_mutex_t = {

      Type = Normal,

      Status = Acquired, possibly with waiters,

      Owner ID = 4319,

      Robust = No,

      Shared = No,

      Protocol = None

    }

  }

p mutex2:

{

  <std::__mutex_base> = {

    _M_mutex = pthread_mutex_t = {

      Type = Normal,

      Status = Acquired, possibly with waiters,

      Owner ID = 4320,

      Robust = No,

      Shared = No,

      Protocol = None

    }

  }

mutex1的當前所屬線程是4319(相對線程號爲2),mutex2的當前所屬線程是4320(相對線程號爲3。同時,mutex1及mutex2中的Status字段均表示其已經被獲取,並且可能有等待者。

結論

將上述分析結果以表格形式彙總:

相對線程號

線程號

擁有鎖

等待鎖

2

4319

mutex1

mutex2

3

4320

mutex2

mutex1

從彙總結果看,線程4319,43202形成了死鎖,導致程序掛起。

掃描二維碼,關注“清遠的夢囈”公衆號,發現更多文章

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章