专栏首页蓝天一个死锁分析过程

一个死锁分析过程

一小伙说他的程序死锁了,让帮忙看看。对死锁问题,首先祭出GDB这一神器。

(gdb) bt #0  0xffffe410 in __kernel_vsyscall () #1  0xf7fa790e in __lll_mutex_lock_wait () from /lib/libpthread.so.0 #2  0xf7fa3a8b in _L_mutex_lock_81 () from /lib/libpthread.so.0 #3  0xf7fa35be in pthread_mutex_lock () from /lib/libpthread.so.0 #4  0x08316692 in mooon::sys::CLock::lock (this=0x89f59e0)

第一步的目标是找到锁被谁持有了,这只需要找到死锁的位置,然后查看pthread_mutex_t.__owner值是什么。接下来使用GDB的“info threads”命令找到持有的线程。

找到持有的线程后,查看它的调用栈:

#0  0xffffe410 in __kernel_vsyscall () #1  0xf7daea16 in __gxx_personality_v0 () from /lib/libc.so.6 #2  0xf7ddccbc in usleep () from /lib/libc.so.6 #3  0x0825a374 in CSHMPkg::LockWait (this=0xddb3ebb0) at SHMPkg.cpp:221

这个时候需要看对应的源代码:

bool CSHMPkg::LockWait() {   if (strlen(m_lockFilePath) <= 0) return false;   while (!m_readLock.LockFile(m_lockFilePath))     usleep(10);   return true; }

进一步看加文件锁的代码:

bool CFileLock::LockFile(const char* filePath) {   m_fd = open(filePath, O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR);   if(m_fd == -1)     return false;   if (write_lock(m_fd, 0, SEEK_SET, 1) == -1) {     close(m_fd);     m_fd = -1;     return false;   }   return true; }

初步估计while处死循环了,在usleep处打个断点可轻松确定是否死循环。结果确认这里是死循环了。因此问题在LockFile函数,它应当是返回了false。通过单步调试,发现是open失败。检查文件filePath存在,且权限正常,需要找出open失败的原因。

因为open是个系统调用,因此只需要知道errno值即可知道原因。但errno是个宏,不能直接打印,找到宏errno的定义:

#   define errno (*__errno_location ())

在GDB中调用__errno_location(),发现errno的值为24

#define EMFILE 24 /* Too many open files */

到这里,问题已清楚,执行shell命令ulimit -a查看,发现“open files”值为1024,在当下的服务器,1024是一个比较小的值。程序中大量采用redis集群直连,对fd的需求很大,进一步执行“netstat -antp”或lsof也可以看到。

因此解决办法是调大“open files”值,临时可使用ulimit调大,但一般还是得修改文件limits.conf。有关limits.conf,可阅读另一博文《源码解读Linux的limits.conf文件》。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 常用vim设置

        \ if line("'\"")>0&&line("'\"")<=line("$") |

    一见
  • 编译期强制函数参数为字符串常量

    一见
  • 需要使用一致性哈希吗?

    在普通的哈希中,如果节点个数(分母)发生变化,原先的次序会被完全打乱重来,一致性哈希解决了这个问题。实际可看成普通的哈希对着的是物理节点,而一致性哈希对着的是虚...

    一见
  • 0807-6.2.0-CDSW中Session列表和team分析

    本文主要讲述了几种查看CDSW中Session列表的方式,以及对他们的值进行了对比。

    Fayson
  • 兼容Qt4/Qt5版本Qml控件RoundRectangle

    Qt君
  • springboot服务优雅关机脚本

    自从使用springboot开发项目后,服务很多时候都是打成jar包,然后通过 java -jar xx.jar 的方式来启动程序的。

    java乐园
  • 格拉姆-施密特正交化说明

    法线贴图一章节涉及到TNB-切线空间。切线空间在坐标变换过程中,可能偏离,TNB需要重新正交化。最重要的一步是T N正交化。 涉及到的代码片段如下: 重点理...

    用户1068165
  • IDEA上使用Kotlin插件出现的几个小问题

    2017-07-04 by Liuqingwen | Tags: Kotlin | Hits

    IT自学不成才
  • 消费电子产品行业电商平台解决方案

    电子行业除了消费电子之外,还有半导体、LED、汽车电子、元器件和安防等等子行业,消费电子产业追求的是高质量、低成本、快速响应,将终端客户价值最大化,消费电子产品...

    数商云
  • README.md

    README.md文件是一个项目的入门手册,里面介绍了整个项目的使用、功能等等。所以README文件写得好不好,关系到这个项目能不能更容易的被其他人了解和使用。

    wade

扫码关注云+社区

领取腾讯云代金券