中文
注册
我要评分
文档获取效率
文档正确性
内容完整性
文档易理解
在线提单
论坛求助

案例1:死锁导致系统崩溃

问题现象

某软件在服务器运行,概率性出现死机问题。

定位过程

  1. 配置kdump服务,并开启KASAN服务,复现问题。
  2. 问题长时间未复现,关闭KASAN服务,复现问题。
  3. 确认生成vmcore文件,使用Crash调试vmcore文件,如下图所示,确认出现blocked tasks问题。

  4. 根据堆栈信息,确认是kubelet进程申请锁失败导致死锁问题出现。
  5. 从上图日志可以看到,“__netlink_dump_start”这个函数调用了“mutex_lock”这个函数,是它持有了锁。
  6. 查看“__netlink_dump_start”内核源码,如下图所示。

    可以看到是nlk这个结构体中的“cb_mutex”成员作为“mutex_lock”函数的入参。

  7. 查看“cb_mutex”在结构体变量nlk中的偏移,如下图所示。

    可以看到“cb_mutex”在结构体变量nlk中的偏移是920。

  8. 反汇编“__netlink_dump_start”函数,如下图所示。

    看到有汇编操作ldr x0, [x0, #920],结合上面分析,该处就是将地址从nlk的初始地址,移动到其成员变量“cb_mutex”中。因此在该命令前x0寄存器存储了nlk的初始地址。但此时仍不知道到x0寄存器的值是多少。但可以从前面汇编操作mov x19, x0看到,寄存器内容被拷贝到x19中。根据x19寄存器的特征,x19寄存器的值,将在子函数“mutex_lock”调用时保存。

  9. 反汇编“mutex_lock”函数,如下图所示,根据汇编操作str x19, [sp,#16],在mutex_lock函数中将x19保存到sp+16的地方。

  10. 查看“mutex_lock”的栈帧值,为ffff00089a9efae0,如下图所示。nlk结构体变量地址为:ffff00089a9efae0 + 0x10 = ffff00089a9efaf0。

  11. 获取nlk结构体变量内存位置。
    1
    2
    crash> rd 0xffff00089a9efaf0
    ffff00089a9efaf0: ffffa05fc828f800
    
  12. 获取mutex_lock时锁的位置。
    1
    2
    crash> struct netlink_sock.cb_mutex ffffa05fc828f800 –x
    cb_mutex = 0xffff000008e6e7b0 <rtnl_mutex>
    
  13. 查看mutex锁结构体。
    1
    crash> struct mutex 0xffff000008e6e7b0 –x
    

    确认锁的持有者为0xffffa03b9dd80000(因为最后三位是标志位,并非实际锁持有者地址,最后三位赋值为0)。

  14. 查看锁持有者所属进程PID,如下图所示。

  15. 查看其它有哪些进程在请求这把锁。

  16. 查看相关进程代码,确认出现死锁问题原因。修改代码,避免死锁,重新编译运行程序,未出现问题,确认修改合入,问题解决。