GDB排查死锁问题

不是专业开发,偶尔遇到死锁问题,请前辈检查,记录如下:

首先,通过如下指令,找到名为hw的进程:

ps -ef |grep hw

然后,进入gdb:

sudo gdb

关闭分页功能:

set pagination off

通过attach进入到进程中(假设hw进程为3223):

attach 3223

对所有的线程执行bt指令(栈回溯)

thread apply all bt

GDB排查死锁问题_第1张图片

 我们发现某个线程中持续显示锁的等待:

__lll_lock_wait

所以注意到mutex的值是0x55ecaba12a40,使用

print *((pthread_mutex_t *)0x55ecaba12a40) 

可以看到其在某个函数中正在持锁等待。(这句话的意思和C语言类似,把地址0x55ecaba12a40中的值枪值转换成pthread_mutex_t类型的指针,并采用*取出实际的值打印一下。

下面内容源自chatgpt,请教了大佬,好多是错的,因此内容仅供参考。。

`pthread_mutex_t` 是用于在多线程环境下实现互斥锁的 POSIX 标准的结构体类型。它的定义通常包含以下成员:

```c

typedef struct

{

int __lock; // 用于存储锁状态的整数,可以是 0 或 1。

int __count; // 当前持有该锁的线程数目。 这里有误,实际表示std::recursive_mutex加锁的次数

int __owner; // 当前持有该锁的线程 ID。

int __nusers; // 正在尝试获取该锁的线程数目。  这里有误,实际表示持有该锁的线程数目

int __kind; // 锁的类型,可以是 PTHREAD_MUTEX_NORMAL、PTHREAD_MUTEX_RECURSIVE 或 PTHREAD_MUTEX_ERRORCHECK。

int __spins; // 自旋等待的次数。

__pthread_list_t __list; // 链表头结构体,用于维护等待该锁的线程。

} pthread_mutex_t;

```

需要注意的是,这个结构体的具体实现可能会因不同的操作系统、编译器或代码库而有所不同。此外,由于这个结构体是 POSIX 标准的一部分,因此其成员的名称前缀通常是双下划线 `__`。

在 POSIX 标准中,`__lock` 字段表示互斥量或锁的锁定状态,可以是 0 或 1。具体含义如下:

- 当 `__lock` 字段为 0 时,表示互斥量或锁当前处于未锁定状态,即没有线程持有该互斥量或锁。

- 当 `__lock` 字段为 1 时,表示互斥量或锁当前处于锁定状态,即某个线程持有了该互斥量或锁。

- 当 `__lock` 字段为 2 时,表示互斥量或锁的状态值被意外修改,可能是代码出现了错误。

(ps:这里不准确)

需要注意的是,这里的 `__lock` 字段通常是 POSIX 系统实现所使用的,具体实现可能因操作系统、编译器或代码库的不同而有所不同。因此,在具体应用中,应该根据实际情况进行解释。

经过发现,此时1580线程根本就不存在,以至于卡死在这个函数流程中。

总之通过这种方式可以排查死锁问题。这次的死锁发现,发生在第三方sdk当中,于是这个锅甩到了供应商那里。。

ps:至于__lock = 2 到底是不是意味着异常,这点存疑,所以试了一下,用三个进程分别去拿锁, 打印状态:

发现刚开始,在gdb中直接打印锁(p lock_a) 其中lock_a为锁的变量名,发现__lock字段为0。当有一个线程持有锁以后,__lock字段变为1。当第二个线程开始尝试持有lock_a的时候,__lock就会变成2。第三个线程没有拿到,等待过程中lock_a仍然为2。

因此,结论是:

__lock为0时,代表锁没有被持有;

__lock为1时,代表有人持有锁;

__lock为2时,代表有地方持有锁,另一个地方正处于异常等待当中。

 

你可能感兴趣的:(Linux和ROS,linux,死锁,gdb)