案例1:死锁导致系统崩溃
问题现象
某软件在服务器运行,概率性出现死机问题。
定位过程
- 配置kdump服务,并开启KASAN服务,复现问题。
- 问题长时间未复现,关闭KASAN服务,复现问题。
- 确认生成vmcore文件,使用Crash调试vmcore文件,如下图所示,确认出现blocked tasks问题。
- 根据堆栈信息,确认是kubelet进程申请锁失败导致死锁问题出现。
- 从上图日志可以看到,“__netlink_dump_start”这个函数调用了“mutex_lock”这个函数,是它持有了锁。
- 查看“__netlink_dump_start”内核源码,如下图所示。
可以看到是nlk这个结构体中的“cb_mutex”成员作为“mutex_lock”函数的入参。
- 查看“cb_mutex”在结构体变量nlk中的偏移,如下图所示。
可以看到“cb_mutex”在结构体变量nlk中的偏移是920。
- 反汇编“__netlink_dump_start”函数,如下图所示。
看到有汇编操作ldr x0, [x0, #920],结合上面分析,该处就是将地址从nlk的初始地址,移动到其成员变量“cb_mutex”中。因此在该命令前x0寄存器存储了nlk的初始地址。但此时仍不知道到x0寄存器的值是多少。但可以从前面汇编操作mov x19, x0看到,寄存器内容被拷贝到x19中。根据x19寄存器的特征,x19寄存器的值,将在子函数“mutex_lock”调用时保存。
- 反汇编“mutex_lock”函数,如下图所示,根据汇编操作str x19, [sp,#16],在mutex_lock函数中将x19保存到sp+16的地方。
- 查看“mutex_lock”的栈帧值,为ffff00089a9efae0,如下图所示。nlk结构体变量地址为:ffff00089a9efae0 + 0x10 = ffff00089a9efaf0。
- 获取nlk结构体变量内存位置。
1 2
crash> rd 0xffff00089a9efaf0 ffff00089a9efaf0: ffffa05fc828f800
- 获取mutex_lock时锁的位置。
1 2
crash> struct netlink_sock.cb_mutex ffffa05fc828f800 –x cb_mutex = 0xffff000008e6e7b0 <rtnl_mutex>
- 查看mutex锁结构体。
1
crash> struct mutex 0xffff000008e6e7b0 –x
确认锁的持有者为0xffffa03b9dd80000(因为最后三位是标志位,并非实际锁持有者地址,最后三位赋值为0)。
- 查看锁持有者所属进程PID,如下图所示。
- 查看其它有哪些进程在请求这把锁。
- 查看相关进程代码,确认出现死锁问题原因。修改代码,避免死锁,重新编译运行程序,未出现问题,确认修改合入,问题解决。
父主题: 系统崩溃