专栏首页皮振伟的专栏[nptl][mutex]老司机带你十分钟定位死锁问题

[nptl][mutex]老司机带你十分钟定位死锁问题

前言:

死锁问题,几乎可以用“自古”来形容。PV原语一出,信号量嵌套使用,就伴随着死锁问题的发生。死锁类问题的解决过程,基本上就是定位到发生死锁的位置以及原因,然后就是修正逻辑错误。这里重点说前者,就是用怎样的手段和方法,快速定位死锁位置和原因。题目中承诺的十分钟,也只是承诺这个过程。

分析:

1,准备条件

gdb :作者窃以为,Linux平台开发,必须会一手gdb。

debug symbol:编译的时候,带着-g选项;编译后,没有strip过。

2,发生了deadlock后,可以用两个办法:

a,gdb attach到目标进程上。

b,kill -6 pid,让进程coredump,使用coredump去分析(如果要使用coredump,需要确定/proc/pid/limits中的Max core file size是否满足大小要求,/proc/sys/kernel/core_pattern是否打开)。

3,开始分析

a,

以上述代码为例:编译生成测试程序deadlock并运行,只能看到两个线程分别enter func1&func2,没有leave。可知发生了deadlock。

b,作者使用了coredump的方式。并生成了deadlock.core。

启动gdb:gdb ./deadlock

加载coredump:core-file deadlock.core

查看线程:info threads,如下图

最后一帧是__lll_lock_wait的都可能是deadlock的发生点。

c,选择需要重点查看的线程:thread 8(如上图,线程8最后一帧停留在了__lll_lock_wait)

查看backtrace:bt

d,分析frame:frame 1(因为frame 1中调用了__GI___pthread_mutex_lock)

分析mutex1信息:p mutex1(因为__GI___pthread_mutex_lock的第一参数就是mutex1)

因为__owner = 3786,可知,mutex1的当前只有线程的tid就是3786.

e,结合代码继续分析当前线程的情况:frame 2

查看自己占用的mutex:p mutex2

因为__owner = 3787,可知,mutex2的当前只有线程的tid就是3787.

f,结合d和e两个步骤,可以知道:线程3787占用mutex2,并且请求mutex1.

g,再次使用c,d,e,f过程分析thread 13,同样可以得知:线程3786占用mutex1,并且请求mutex2.

h,结合f和g的分析结果,那么可以判断出来:当前进程的13个线程中,发生了deadlock的是线程3786和3787,并且线程3786占用mutex1,线程3787占用mutex2。问题分析到这里,作就算初步定位完了。剩下的工就是解决逻辑问题。

i,现在是两个线程卡在了__lll_lock_wait的地方,分析起来相对容易一些,如果是多个线程的最后一帧都是__lll_lock_wait函数,那么需要多花一些时间分析各个mutex的占用者和请求者。分析的过程中,也可以使用thread apply all bt这个命令,简单粗暴,打印出来所有线程的bt。

后记:

工具用的好,可以下班早。

多读LIBC,谁看都说好。

本文分享自微信公众号 - AlwaysGeek(gh_d0972b1eeb60),作者:AlwaysGeek

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-01-17

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • [nptl][pthread]一种判断thread是否在执行的方法

    前言: 主线程中怎么确定某线程是否在执行? 作者遇到这个问题,第一感觉有点蒙。翻了一下glibc的代码,算是找到一个比较好的办法吧。 分析: 1,变量控制 ...

    皮振伟
  • [x86][kvm]avx512指令相关

    前文《[x86][linux]AVX512指令引起的进程crash》中,介绍了一次因为avx512指令导致的进程crash。

    皮振伟
  • [x86][linux]AVX512指令引起的进程crash

    问题背景: 在开发机上编译ovs,在目标机器上运行,出现来ovs-vswitchd崩溃,dmesg得到如下信息: [ 2807.148361] traps: o...

    皮振伟
  • Java Concurrent synchronized 使用&原理

    sychronized 是Java语法层面的同步策略,可以用来修饰instance变量、object reference(对象引用)、static函数和clas...

    邹志全
  • java基础

    当一个线程需要调用对象的wait()方法的时候,这个线程必须拥有该对象的锁,接着它就会释放这个对象锁并进入等待状态直到其他线程调用这个对象上的notify()方...

    大学里的混子
  • java面试

    当一个线程需要调用对象的wait()方法的时候,这个线程必须拥有该对象的锁,接着它就会释放这个对象锁并进入等待状态直到其他线程调用这个对象上的notify()方...

    大学里的混子
  • Java并行-0.基本概念

    临界区表示被多个线程使用的公共资源,但是每一次只能有一个线程使用它。 比如打印机资源。

    悠扬前奏
  • 猿思考系列2——一文搞懂同步并发套路

    看完上一个章节,相信你已经充分的理解java代码的执行套路了,猿人工厂君也知道,内容对于新手而言,理解起来还是很吃力的,不过上一章节涉及编译原理、类加载机制和一...

    山旮旯的胖子
  • 彻底搞懂 Java 线程池,干啥都不再发憷

    作为 Java 程序员,无论是技术面试、项目研发或者是学习框架源码,不彻底掌握 Java 多线程的知识,做不到心中有数,干啥都没底气,尤其是技术深究时往往略显发...

    一猿小讲
  • 如何暂停一个正在运行的线程?

    停止线程是在多线程开发中很重要的技术点,比如在多线程持续处理业务代码时,由于处理逻辑中有第三方接口异常,我们就假设发送短信接口挂了吧,那么此时多线程调用短信接口...

    niceyoo

扫码关注云+社区

领取腾讯云代金券