多线程+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就在 ...
随机推荐
- android 安全退出应用程序的几种方法
android 安全退出应用程序的几种方法 正常关闭应用程序: 当应用不再使用时,通常需要关闭应用,可以使用以下三种方法关闭android应用: 第一种方法:首先获取当前进程的id,然后杀死该进程.a ...
- 9.7noip模拟试题
题目名称 日历游戏 最大公约数 密码 英文代号 calendar gcd pasuwado 输入文件名 calendar.in gcd.in pasuwado.in 输出文件名 calendar.ou ...
- codevs 2541 幂运算(迭代加深搜索)
/* 一开始想到了简单的深搜 维护当前可用的mi数组 然后回溯用哪个 不断更新新产生的mi 这样的问题是 由于mi不断产生 搜索规模扩大 不好 不好 下面是奇丑的WA掉的代码 做个反面教材 */ #i ...
- Spring框架
Spring框架的根本使命是:简化JAVA开发,为了简化开发,有以下四个策略 基于POJO的轻量级和最小侵入性编程: 通过依赖注入和面向接口实现松耦合: 基于切面和惯性进行声明式编程: 通过切面和模板 ...
- python3下的super()
大家都知道super是用来解决python钻石多重继承出现的基类重复调用的问题,这个就不赘述了,不了解的请点击. 但是我发现还有个问题在于不是钻石继承时继承先后顺序的问题,也就是如果mixin与继承的 ...
- PC端手机访问跳转手机站点
第一种: var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.sr ...
- APP长时间处于后台,再次调用时提示用户重新登录
第一步:当应用被处于后台时,调用计时器的start()方法,开始计时 在所有Activity继承的BaseSwiBackAct中的 public void onStop() { EventBus.ge ...
- CTE的使用
CTE在SQL2005后的版本提供,丰富了查询的表现形式,下面我们慢慢来看下CTE都能干什么 1.自我递归 ;WITH myaa AS ( SELECT num=1 UNION ALL SELECT ...
- Smarty环境配置
Smaty优点:1.代码分离 2.缓存技术 使用步骤: 1.下载Smaty模板 2.将模板中那个lib文件夹复制到项目中(一般为根目录,并且重命名在此命名为Smarty), 3.配置PHP 1.新建一 ...
- 你好,C++(10)这次的C++考试你过了没有?C++中表示逻辑判断的布尔数据类型
3.4 布尔类型 在日常生活中,我们除了需要使用int类型的变量表示216路公交车:需要使用float类型的变量表示西红柿3.5元一斤,有时候还需要表示一种数据,那就是逻辑状态: “这次的C++考试 ...