GDB死锁调试

1、测试代码

代码中开启两个线程,加锁后轮流输出数据,其中一个线程误将pthread_mutex_unlock(),写成pthread_mutex_lock()代码如下:

int g_tickets = 100;
pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
void* thread_fun1(void * arg)
{
    while(true)
    {
        pthread_mutex_lock(&g_mutex);
        if(g_tickets>0)
        {
            cout<<"thread 1 sell tickets:"<<g_tickets--<<endl;
        }
        else
        {
            //pthread_mutex_unlock(&g_mutex); 
            pthread_mutex_lock(&g_mutex);//误将pthread_mutex_unlock写成pthread_mutex_lock
            break;
        }
        //pthread_mutex_unlock(&g_mutex);
        pthread_mutex_lock(&g_mutex);//误将pthread_mutex_unlock写成pthread_mutex_lock
    }
    return (void*)1;
}
void* thread_fun2(void * arg)
{
    while(true)
    {
        pthread_mutex_lock(&g_mutex);
        if(g_tickets>0)
        {
            cout<<"thread 2 sell tickets:"<<g_tickets--<<endl;
        }
        else
        {
            pthread_mutex_unlock(&g_mutex);
            break;
        }
        pthread_mutex_unlock(&g_mutex);
    }
    return (void*)2;
}
int main()
{
    pthread_t tid1,tid2;
    void *ret1 = nullptr;
    void *ret2 = nullptr;

    pthread_create(&tid1,nullptr,thread_fun1,nullptr);
    pthread_create(&tid2,nullptr,thread_fun2,nullptr);

    pthread_join(tid1,&ret1);
    pthread_join(tid2,&ret2);

    cout<<"ret1:"<<ret1<<endl;
    cout<<"ret2:"<<ret2<<endl;
    return 0;
}

makefile文件

cc =g++ -g -std=c++2a -fmodules-ts
prom = main
deps = $(shell find ./ -name "*.h")
src = $(shell find ./ -name "*.cpp")
obj = $(src:%.cpp=%.o)
lib = -lboost_thread       -lboost_system       -pthread

$(prom):$(obj)
    $(cc) -o $(prom) $(obj) $(lib)
%.o:%.cpp $(deps)
    $(cc) -c $< -o $@ $(lib)

2、编译并运行程序

make
./main

输入结果如下

GDB死锁调试

3、调试

  • 查找测试程序进程号
ps aux | grep main

GDB死锁调试

  • 通过gdb attach死锁进程。
sudo gdb main 23848

GDB死锁调试

  • 使用info threads命令列出所有线程信息

GDB死锁调试

  • 切换到线程2 ,并打印调用栈

GDB死锁调试

  • 切换到线程3,并打印调用栈

GDB死锁调试

  • 打印互斥变量信息,发现锁g_mutex被线程23849获得。而线程23849和23850均在尝试获得锁g_mutex。

GDB死锁调试

  • 通过源码分析,发现thread_fun1中g_mutex在获得锁之后,后续并没有释放锁g_mutex,而且在继续申请锁g_mutex。明显不合理。

GDB死锁调试

GDB死锁调试

上一篇:Mysql中select条件取值写法


下一篇:CentOS7 下启动、关闭、重启、查看MySQL服务