多线程+fork 引发的bug查找
1. 问题描述
某个server SA是一个多线程服务器,主线程会调用fork,再exec生成工作进程SB。
实际上,SA的主线程fork出了一个子线程,但没有执行exec。
# ps ajxf | grep r2server
14022 28342 28341 14022 pts/2 28341 S+ 0 0:00 | \_ grep r2server
1 28046 28037 3823 ? -1 Sl 0 31:25 ./r2server ../conf/r2server.conf
28046 28075 28037 3823 ? -1 S 0 0:00 \_ ./r2server ../conf/r2server.conf
2. 问题定位
2.1 用pstack观察2个进程当前stack状态。
# pstack 28075
#0 0x00007f40f24bf264 in __lll_lock_wait () from /lib64/libpthread.so.0
#1 0x00007f40f24ba508 in _L_lock_854 () from /lib64/libpthread.so.0
#2 0x00007f40f24ba3d7 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3 0x000000000043b407 in r2::log::LogFactory::log_printf(char const*, char const*, int, char const*, int, char const*, ...) ()
发现被lock住了。
google “pthread_mutex_lock owner”找到文献 https://en.wikibooks.org/wiki/Linux_Applications_Debugging_Techniques/Deadlocks,
安装上面的方法,定位:
f 3
(gdb) info reg
rax 0xfffffffffffffe00 -512
rbx 0x7517a0 7673760
rcx 0xffffffffffffffff -1
rdx 0x7f40d9ff86bf 139916512036543
rsi 0x80 128
rdi 0x753fb0 7684016
rbp 0x753fb0 0x753fb0
rsp 0x7f40d9ff85c0 0x7f40d9ff85c0
r8 0x753fb0 7684016
(gdb) p *(pthread_mutex_t*)0x753fb0
$1 = {__data = {__lock = 2, __count = 0, __owner = 28049,
说明当前线程的在等待一个锁,该锁被28049占有了。
# pstack 28049
Thread 1 (process 28049):
#0 0x00007f40f1a65ef3 in epoll_wait () from /lib64/libc.so.6
说明该线程已经释放了这个锁。
因此原因 是多线程+fork引起的bug:进程组28046里的主线程28046调用fork的时候,此时线程28049占用了一个锁A(正在打log),创建了子进程28075。
子进程执行exec前的代码,遇到log_printf调用,去申请锁A。因为锁A是被lock的,因此该进程死锁,执行不了到exec。
进程组28046的线程28049打完log后,释放了锁A(进程组28046和进程28075是两个不同的进程空间,有不同的page table。此时释放锁A会采用copy on write技术,创建一个新的锁A),继续正常执行。
根本原因:由于多线程的存在,某个线程占用了一个锁,因此fork的时候,fork出来的进程地址空间包含了这个被占用的锁。如果在exec之前,调用再申请这个锁,会导致死锁。
3. 解决方案
1. 多线程 or fork二选一。
2. 多线程+fork的时候,fork到exec之间只调用的async—signal function (man 7 singal),因为此时进程状态是unsafe的。
参考文献:
http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them
https://en.wikibooks.org/wiki/Linux_Applications_Debugging_Techniques/Deadlocks
多线程+fork 引发的bug查找的更多相关文章
- Spring 循环引用(一)一个循环依赖引发的 BUG
Spring 循环引用(一)一个循环依赖引发的 BUG Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring 循环 ...
- 记一次PHP7+opcache+zmq出现SIGSEGV 问题的查找(一次不成功的bug查找)
Title: 记一次PHP7+opcache+zmq出现SEGSEGV问题的查找(一次不成功的bug查找) bug来历自述:线上代码PHP环境是5.2,为了提升性能(逼格),于是升级为PHP7并使用 ...
- bug 查找 (二) 从前端找到后端
bug 查找 (二) 从前端找到后端 几天来,组长说我们系统的 apm 数据不正确,最体表现就是前端项目这几天错误统计为 0. 这不正常(没有办法,我们代码写的很烂),因为前端环境很复杂,网络,浏览器 ...
- # bug 查找 (一) 快速记录 IE8 下三个问题
bug 查找 (一) 快速记录 IE8 下三个问题 昨天 pc 端网站上灰度,发现多个在 IE8 下的问题,描述和解决方案如下: 第一个问题是 css 文件过大 现象 把项目所有的 css 打包成单个 ...
- 安卓微信overflow-x overflow-y引发的bug
今天xgo文章图片页上线用微信扫页面发现一个bug,页面可以双击放大缩小. 找了半天原因,发现是图片描述设置了overflow-y引发的bug. 建议在微信场景里满屏显示不能滚动的页面里慎用overf ...
- QByteArray引发的bug
QByteArray引发的bug 在接收UDP数据的函数里,有如下代码片段 if(0x10 == data.size() && 0xCA == (unsigned char)data. ...
- 一场由fork引发的超时,让我们重新探讨了Redis的抖动问题
摘要:一次由fork引发的时延抖动问题. 背景介绍 华为云数据库GaussDB(for Redis) 是一款基于计算存储分离架构,兼容Redis生态的云原生NoSQL数据库:它依靠共享存储池实现了强一 ...
- 一个由单例模式在多线程环境下引发的 bug
问题症状 HTTP 日志系统,老是出现日志信息覆盖的情况.比如同时调用 A 接口和 B 接口,B 接口请求响应信息变成了 A 接口请求响应相关信息.这个问题在并发量大的情况下越来越严重. 问题初步分析 ...
- 一次关于使用status作为变量引发的bug及思考
这个bug出现在一年前,当时自己大学还没毕业,刚刚进入一家公司实习.那个时候还没有用seajs或者requirejs那样的模块化管理的库,也没有用一个自执行的函数将要执行的代码包裹起来,于是bug就在 ...
随机推荐
- OpenGL ES2.0基础入门
1.OpenGL ES 1.x渲染管线(又称为渲染流水线) (1).基本处理: 基本处理主要是设定3D空间中物体的顶点坐标.顶点对应的颜色.顶点的纹理坐标等属性,并且指定绘制方式. 常见的绘制方式有: ...
- python文件处理--笔记
之前一段时间一直在忙着写毕业论文,盲评搞得人心惶惶,以致于都没有看书,最近需要补上前面落下的东西. <Python3程序开发指南> 1.二进制数据的读写 二进制格式通常是占据磁盘空间最小. ...
- codevs 1515 跳
/* 画矩阵找规律发现是杨辉三角 Cg (i,j)= C (i+j,i); 贪心走的话 沿着0行(列)一直走然后拐直角 拐弯后每个格子都累加 Cg (n,0) + Cg (n,1) + Cg (n,2 ...
- codevs4189字典(字典树)
/* 本字典树较弱 只支持插入单词 查询单词. 特殊的 bool变量w 标记此字母是不是某个单词的结束 (然而这个题并没卵用) */ #include<iostream> #include ...
- c# hasvalue属性
// 数据类型? 表示参数的值可以为null空,此时这个参数可调用属性hasvalue来判断,此参数是否有除了null以外的值;进而进行其它的工作 //必须要加?才可用hasvalue属性 priva ...
- Android中的BroadCast静态注册与动态注册
1.静态注册 新建MyBroadcast类继承BroadcastReceiver,实现onReceive方法 /** * Author:JsonLu * DateTime:2015/9/21 16:4 ...
- 关于电脑开机不出现桌面即不启动explorer.exe桌面程序--------正解
针对这个问题,一开始的思路是,把自己写的界面小程序(Win.exe)放在Windows启动文件夹中, 效果到是界面程序自启动了,但是还是先出现的桌面,然后才的启动的界面程序(Win.exe),并不是我 ...
- .Net操作XML文件
//设置配置文件物理路径 public string xmlPath = "/manage/spider/config.xml"; protected void Page_Load ...
- MySQL拷贝表的几种方式
假如我们有以下这样一个表: id username password ----------------------------------- 1 admin * ...
- iOS程序的完整启动过程(有storyboard)
1.先执行main函数,main内部会调用UIApplicationMain函数 2.UIApplicationMain函数里面做了什么事情:1> 创建UIApplication对象 2> ...