死锁往往是概率性发生,多线程在特定时序下出现。难复现,多线程动态作用,此类问题排查往往很费劲。下面介绍一个简易的排查方法。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/time.h>
#include <map>
#include <set>
#include <sys/prctl.h>
using namespace std;
typedef struct _LOCK_TAG_INFO{
const char* tags;
int line;
pthread_t pid;
struct timeval cur_time;
char threadName[16];
string str;
pthread_mutex_t *pmutex;
int flag;
}LOCK_TAG_INFO;
typedef struct _LOCK_MANGER{
set<LOCK_TAG_INFO* > lockSet;
map<pthread_mutex_t *,LOCK_TAG_INFO > lockMap;
pthread_mutex_t lockMuetx;
}LOCK_MANGER;
LOCK_MANGER g_lockManger;
pthread_mutex_t lockMuetx_1;
pthread_mutex_t lockMuetx_2;
int m_mutex_lock(pthread_mutex_t *muet_t, const char *tag,int line)
{
LOCK_TAG_INFO lockTagInfo;
lockTagInfo.tags = tag;
lockTagInfo.line = line;
lockTagInfo.pmutex = muet_t;
gettimeofday(&lockTagInfo.cur_time, NULL);
lockTagInfo.threadName[0] = 0;
prctl(PR_GET_NAME,lockTagInfo.threadName);
pthread_mutex_lock(&g_lockManger.lockMuetx);
g_lockManger.lockSet.insert(&lockTagInfo);
pthread_mutex_unlock(&g_lockManger.lockMuetx);
pthread_mutex_lock(muet_t);
pthread_mutex_lock(&g_lockManger.lockMuetx);
g_lockManger.lockSet.erase(&lockTagInfo);
gettimeofday(&lockTagInfo.cur_time, NULL);
g_lockManger.lockMap[muet_t] = lockTagInfo;
pthread_mutex_unlock(&g_lockManger.lockMuetx);
return 0;
}
int m_mutex_unlock(pthread_mutex_t *muet_t)
{
pthread_mutex_lock(&g_lockManger.lockMuetx);
g_lockManger.lockMap.erase(muet_t);
pthread_mutex_unlock(&g_lockManger.lockMuetx);
pthread_mutex_unlock(muet_t);
return 0;
}
int muteDump(void)
{
LOCK_TAG_INFO *lockTagInfo = NULL;
struct timeval cur_time;
gettimeofday(&cur_time, NULL);
pthread_mutex_lock(&g_lockManger.lockMuetx);
{
std::set<LOCK_TAG_INFO*>::iterator iter;
iter = g_lockManger.lockSet.begin();
while(iter != g_lockManger.lockSet.end()){
lockTagInfo = *iter;
unsigned int t = (cur_time.tv_sec - lockTagInfo->cur_time.tv_sec)*1000 + (cur_time.tv_usec/1000 - lockTagInfo->cur_time.tv_usec/1000);
printf("try p=%p t:%dsec-%dms pn:%s at:%s %d\n",lockTagInfo->pmutex,t/1000,t%1000,lockTagInfo->threadName,lockTagInfo->tags,lockTagInfo->line);
iter++;
}
}
{
std::map<pthread_mutex_t *,LOCK_TAG_INFO >::iterator iter;
iter = g_lockManger.lockMap.begin();
while(iter != g_lockManger.lockMap.end()){
if(pthread_mutex_trylock(iter->first) == 0){
pthread_mutex_unlock(iter->first);
}else{
LOCK_TAG_INFO lockTagInfo = iter->second;
unsigned int t = (cur_time.tv_sec - lockTagInfo.cur_time.tv_sec)*1000 + (cur_time.tv_usec/1000 - lockTagInfo.cur_time.tv_usec/1000);
printf("get p=%p t:%dsec-%dms pn:%s at:%s %d\n",lockTagInfo.pmutex,t/1000,t%1000,lockTagInfo.threadName,lockTagInfo.tags,lockTagInfo.line);
}
iter++;
}
}
pthread_mutex_unlock(&g_lockManger.lockMuetx);
return 0;
}
void* pthread_t1(void* p)
{
prctl(PR_SET_NAME,"pthread_t1");
while(1){
m_mutex_lock(&lockMuetx_1,__FILE__,__LINE__);
usleep(10*1000);
m_mutex_lock(&lockMuetx_2,__FILE__,__LINE__);
usleep(10*1000);
m_mutex_unlock(&lockMuetx_2);
m_mutex_unlock(&lockMuetx_1);
}
}
void* pthread_t2(void* p)
{
prctl(PR_SET_NAME,"pthread_t2");
while(1){
m_mutex_lock(&lockMuetx_2,__FILE__,__LINE__);
usleep(10*1000);
m_mutex_lock(&lockMuetx_1,__FILE__,__LINE__);
m_mutex_unlock(&lockMuetx_1);
m_mutex_unlock(&lockMuetx_2);
}
}
int main()
{
pthread_t phthread1,phthread2;
pthread_create(&phthread1, NULL, pthread_t1, NULL);
pthread_create(&phthread2, NULL, pthread_t2, NULL);
sleep(1);
muteDump();
return 0;
}
执行结果如下:
try p=0x55bff55010e0 t:0sec-990ms pn:pthread_t2 at:lockDumpDemo.cpp 133
try p=0x55bff5501120 t:0sec-990ms pn:pthread_t1 at:lockDumpDemo.cpp 121
get p=0x55bff55010e0 t:1sec-1ms pn:pthread_t1 at:lockDumpDemo.cpp 119
get p=0x55bff5501120 t:1sec-1ms pn:pthread_t2 at:lockDumpDemo.cpp 131