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. 实时控制软件第一次作业--CNC软件系统分析

    作者:李君威U201310747 一.该系统有哪些强实时功能需求?需要对哪些实时事件进行实时响应,对允许的实时延迟的数量级进行估计. 答:在数控系统中,位置控制.插补计算.紧急控制等严格实时性任务需要 ...

  2. Html中src、href的相对路径与绝对路径

    What is a path? Why is this something developers should care about? A path is simply the location of ...

  3. ECLIPSE TOMCAT CONFIG JSTL

    {LJ?Dragon}[标题]Eclipse 配置 JSTL标签库 {LJ?Dragon}[Diary]2017年,愉快的开始:当和他们离别时,感觉失去了整个世界.........   1.JSTL简 ...

  4. ios中键值编码kvc和键值监听kvo的特性及详解

    总结: kvc键值编码  1.就是在oc中可以对属性进行动态读写(以往都是自己赋值属性)           2. 如果方法属性的关键字和需要数据中的关键字相同的话                  ...

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

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

  6. Linux TCP队列相关参数的总结

    作者:阿里技术保障锋寒 原文:https://yq.aliyun.com/articles/4252 摘要: 本文尝试总结TCP队列缓冲相关的内核参数,从协议栈的角度梳理它们,希望可以更容易的理解和记 ...

  7. iOS 类似美团外卖 app 两个 tableView 联动效果实现

    写在前面 首先声明哈,不是广告,我就是用的时候觉得这个功能比较好玩,就想着实现了一下.效果如图: 接下来简单的说一下思路吧~ 大体思路 可能我们看到这种功能的实现的时候,首先想着的是我在这个控制器中左 ...

  8. ASP.NET-FineUI开发实践-17

    我又不用FineUI开发,所以FineUI项目经验等于0,最近在忙别的,所以也没工夫研究.积累了论坛和群里的问题,写下来留个备份 1.在grid可编辑单元格中,如果需要在点击该单元格时,单元格中所有文 ...

  9. Windows Azure上的Odoo(OpenERP)-1.创建Ubuntu虚拟机,安装PostgreSQL 数据库

    前提是您必须拥有Windows Azure的账号,如果没有的话,可以去Windows Azure 中国区网站申请免费试用账号.哈哈,我就是第一批申请的试用账号,感觉自己挺幸运的.申请的过程就不写了,请 ...

  10. ASP.NET实现从服务器下载文件2

    转:http://lanhy2000.blog.163.com/blog/static/436786082011105104110713/    假设在服务器的根目录下有个名为Download的文件夹 ...