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查找的更多相关文章

  1. Spring 循环引用(一)一个循环依赖引发的 BUG

    Spring 循环引用(一)一个循环依赖引发的 BUG Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring 循环 ...

  2. 记一次PHP7+opcache+zmq出现SIGSEGV 问题的查找(一次不成功的bug查找)

    Title:  记一次PHP7+opcache+zmq出现SEGSEGV问题的查找(一次不成功的bug查找) bug来历自述:线上代码PHP环境是5.2,为了提升性能(逼格),于是升级为PHP7并使用 ...

  3. bug 查找 (二) 从前端找到后端

    bug 查找 (二) 从前端找到后端 几天来,组长说我们系统的 apm 数据不正确,最体表现就是前端项目这几天错误统计为 0. 这不正常(没有办法,我们代码写的很烂),因为前端环境很复杂,网络,浏览器 ...

  4. # bug 查找 (一) 快速记录 IE8 下三个问题

    bug 查找 (一) 快速记录 IE8 下三个问题 昨天 pc 端网站上灰度,发现多个在 IE8 下的问题,描述和解决方案如下: 第一个问题是 css 文件过大 现象 把项目所有的 css 打包成单个 ...

  5. 安卓微信overflow-x overflow-y引发的bug

    今天xgo文章图片页上线用微信扫页面发现一个bug,页面可以双击放大缩小. 找了半天原因,发现是图片描述设置了overflow-y引发的bug. 建议在微信场景里满屏显示不能滚动的页面里慎用overf ...

  6. QByteArray引发的bug

    QByteArray引发的bug 在接收UDP数据的函数里,有如下代码片段 if(0x10 == data.size() && 0xCA == (unsigned char)data. ...

  7. 一场由fork引发的超时,让我们重新探讨了Redis的抖动问题

    摘要:一次由fork引发的时延抖动问题. 背景介绍 华为云数据库GaussDB(for Redis) 是一款基于计算存储分离架构,兼容Redis生态的云原生NoSQL数据库:它依靠共享存储池实现了强一 ...

  8. 一个由单例模式在多线程环境下引发的 bug

    问题症状 HTTP 日志系统,老是出现日志信息覆盖的情况.比如同时调用 A 接口和 B 接口,B 接口请求响应信息变成了 A 接口请求响应相关信息.这个问题在并发量大的情况下越来越严重. 问题初步分析 ...

  9. 一次关于使用status作为变量引发的bug及思考

    这个bug出现在一年前,当时自己大学还没毕业,刚刚进入一家公司实习.那个时候还没有用seajs或者requirejs那样的模块化管理的库,也没有用一个自执行的函数将要执行的代码包裹起来,于是bug就在 ...

随机推荐

  1. swiper.js 移动端触摸滑动插件

    API链接: http://www.swiper.com.cn/api/start/2014/1218/140.html <body> <div class="swiper ...

  2. iphone匹配邮箱的正则表达式

    NSString *str = [NSString stringWithString:@"\\b([a-zA-Z0-9%_.+\\-]+)@([a-zA-Z0-9.\\-]+?\\.[a-z ...

  3. 小学生玩ACM----深搜

    Square Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Su ...

  4. 实现O(1)时间复杂度带有min和max 函数的栈

    仅仅是演示实现.不考虑栈使用的数据结构是vector 还是其它容器. 代码例如以下 #include <iostream> #include <vector> using na ...

  5. linux常用命令 http://mirrors.163.com/ubuntu-releases/12.04/

    由于记忆力有限,把平时常用的Linux命令整理出来,以便随时查阅: linux 基本命令 ls     (list 显示当前目录下文件和目录 ls -l 详细显示 =ll ) [root@linux ...

  6. MYSQL 体系结构图-LRU FREELIST FLUSH LIST

  7. Java Math 类中的新功能--浮点数

    Java™语言规范第 5 版向 java.lang.Math和 java.lang.StrictMath添加了 10 种新方法,Java 6 又添加了 10 种.这个共两部分的系列文章的 第 1 部分 ...

  8. ubuntu vim YouComlpeteMe配置

    使用vundle安装时,在.vimrc中添加 Plugin 'Valloric/YouCompleteMe' 使用Bundle会安装失败原因未知 YCM编译时附加选项--system-libclang ...

  9. Ubuntu下Qt项目的部署

    部署涉及到以下内容: 1. 程序执行文件: 2. 动态链接库: 3. Qt的一些插件(plugins),例如图片插件(imageformats),数据库插件(sqldrivers): 4. 其他资源文 ...

  10. Android 设计模式之观察者模式(转载自:“http://blog.csdn.net/fangchongbory/article/details/7774044”)

    /* * 观察者模式 *      定义对象间的一种一个(Subject)对多(Observer)的依赖关系,当一个对象的状态发送改变时,所以依赖于它的 * 对象都得到通知并被自动更新 * * 当然, ...