多线程死锁的Gdb排查案例
 

事由:完成的服务器程序会在运行几天后,突然所有的服务停止,并导致CPU的占用率突高

缘由:由于把服务器重启后服务重新变为正常,初步判断原因是某种原因造成了死循环,或者是线程锁产生了死锁现象

排查过程:使用gdb调试出问题的服务器程序,使用info threads查看各个线程,使用t n选择某个线程,使用bt查看当前的线程状况,发现线程1和线程2没有问题,线程3-5都在锁定状态停止

线程3:

mutex1锁定
rwlock1锁定

线程4:

rwlock1锁定
mutex2锁定

线程5:

mutex1锁定

判断:

因为线程3中mutex1已经锁定,所以线程5的状态正常

因为线程4中rwlock1已经锁定,所以线程3的状态正常

于是,判断线程4是死锁的主要原因

检查线程4锁住处的代码,发现

pthread_mutex_lock(&globalMutex);
ofstream fout;
fout.open(fileName,ios::app);
if ( !fout)
{
   printErr(fileName);
   return ;
}

fout.write(oneStrTicket.c_str(),oneStrTicket.size());
fout.close();

pthread_mutex_unlock(&globalMutex);

问题查出。

心得:在复杂系统中使用锁机制,最好使用对象的构造和析构来加解锁(Guard),这样可以减少人为地忽略某次解锁而造成死锁的情况。另一种比较土的办法,在使用锁的程序中,不要在程序中间使用retuen, 而使用goto函数跳转至解锁并退出函数的位置

疑问:搞不清楚为什么死锁后,进程所消耗的cpu资源反而上升了