这两天有同学使用数据校验工具时发现进程hang住了,也不知道什么原因,我简单看了看进程堆栈,问题虽然很简单,但能导致程序hang住,也一定不是小问题。简单说明下程序组件的结构,程序由两部分构成,dbchk和dbchk_inner,dbchk采用python代码实现,dbchk_inner采用C语言实现。dbchk负责并发控制,dbchk_inner则负责具体的校验任务。用户通过运行dbchk命令即可达到校验的目的。进程关系如下:

$ pstree 18649

dbchk─┬─sh───dbchk_inner───2*[{scandiff}]

└─{dbchk}

回到问题本身,我用测试用例复现了hang住了场景,查看了dbchk和dbchk_inner的堆栈信息,信息如下:

dbchk进程18649堆栈信息:

$ pstack 18649

Thread 2 (Thread 0x7f4343fff700 (LWP 18658)):

#0 0x000000346f80f09d in waitpid () from /lib64/libpthread.so.0

#1 0x000000347190ff8a in ?? () from /usr/lib64/libpython2.6.so.1.0

#2 0x00000034718de706 in PyEval_EvalFrameEx () from /usr/lib64/libpython2.6.so.1.0

#3 0x00000034718e0797 in PyEval_EvalCodeEx () from /usr/lib64/libpython2.6.so.1.0

dbchk_inner进程18660堆栈信息:

pstack 18660

#0 0x000000346f4da3dd in write () from /lib64/libc.so.6

#1 0x000000346f470fd3 in _IO_new_file_write () from /lib64/libc.so.6

#2 0x000000346f470e9a in _IO_new_file_xsputn () from /lib64/libc.so.6

#3 0x000000346f46705d in fwrite () from /lib64/libc.so.6

#4 0x00000000004136f0 in Scanner::run(unsigned int) ()

可以看到父进程dbchk在卡在waitpid()函数,这个容易理解,它应该在等待子进程dbchk_inner结束;再看子进程dbchk_inner,dbchk_inner卡在fwrite()函数,这个就有点奇怪了,为啥写会被阻塞呢?首先想到的是磁盘空间不够了?看了下磁盘空间还有很大的剩余,那还有什么可能导致write卡住,还有一种可能就是缓冲区满了,写不下去。

基于这个思考,回头看看dbchk的代码

pio = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).wait()

可以看到程序里使用了Popen的wait函数,这可以解释父进程为啥会卡住,因为子进程没有执行完;注意Popen的参数,将stdout和stderr输出重定向到了subprocess.PIPE,这个值表示父子进程之间的管道。那么子进程写缓冲区卡住,应该就是因为PIPE的缓冲区满了。为啥会满呢,一是产生的数据太多;另一方面是没有进程去缓冲区去取数据,导致缓冲区只进不出。PIPE缓冲区默认值大小4096个字节,这个可以通过ulimit -a得到,8*512=4096字节,并且这个值不可以修改的,因为值是定义在linux的头文件里面,除非你重新编译linux内核。

$ ulimit -a

core file size (blocks, -c) 0

……

pipe size (512 bytes, -p) 8

好了问题找到了,PIPE缓冲区满是罪归祸首,如何解这个问题?

1.不将stdout和stderr重定向管道,直接输出

2.程序控制输出到管道数据的大小

管道在进程间通信(IPC)使用很广泛,shell命令就使用的很广泛。比如:

ps –aux | grep mysqld

上述命令表示获取mysqld进程相关的信息。这里ps和grep两个命令通信就采用了管道。管道有几个特点:

1.      管道是半双工的,数据只能单向流动,ps命令的输出是grep的输出

2.      只能用于父子进程或兄弟进程通信,这里可以认为ps和grep命令都是shell(bash/pdksh/ash/dash)命令的子进程,两者是兄弟关系。

3.      管道相对于管道两端的进程而言就是一个文件,并且只存在于内存中。

4.      写入端不断往管道写,并且每次写到管道末尾;读取端则不断从管道读,每次从头部读取。

到这里大家可能会有一个疑问,管道两端的进程,写入进程不断的写,读取进程不断的读,那么什么时候结束呢?比如我们刚刚这个命令很快就结束了,它的原理是怎么样的呢?对于管道,这里有两个基本原则:

1.当读一个写端已经关闭的管道时,在所有数据被读取后,read返回0,以指示达到文件结束处。

2.当写一个读端已经关闭的管道时,会产生sigpipe信息。

结合这个例子,当ps写管道结束后,就会自动关闭,此时grep进程read就会返回0,然后自动结束。

参考文档:

《UNIX环境高级编程》

http://blog.chinaunix.net/uid-26833883-id-3227144.html

一次进程hang住问题分析。。。的更多相关文章

  1. 一次数据库hang住的分析过程

    现象: 普通用户和sysdba都无法登陆,业务中断 分析过程: 1.先做hanganalyze和systemstate dump $sqlplus -prelim "/as sysdba&q ...

  2. truncate表hang住(等待时间较长),出现enq:RO fast object reuse等待事件

    有一个应用truncate表等待了一晚上,一个定时任务,跑了几年了,今天早上来发现昨晚没有执行完成,hang住了,查询发现等待事件 fast object reuse. 10.2.0.4的库 Bug ...

  3. debug实战:进程Hang+High CPU

    最近几周都在解决程序不稳定的问题,具体表现为程序(多进程)时不时的Hang住,同时伴随某个进程的High CPU.跟踪下来,基本都是各种死锁引起的.这里选取一个典型的场景进行分析. 1.抓dump分析 ...

  4. 如何诊断oracle数据库运行缓慢或hang住的问题

    为了诊断oracle运行缓慢的问题首先要决定收集哪些论断信息,可以采取下面的诊断方法:1.数据库运行缓慢这个问题是常见还是在特定时间出现如果数据库运行缓慢是一个常见的问题那么可以在问题出现的时候收集这 ...

  5. ShellExecuteEX打开iqy文件导致excel hang的原因分析

    1. 问题 当在console中调用API ShellExecuteEx打开"test.iqy"文件时,发现excel会hang住,console退出后excel才会响应,但直接双 ...

  6. 11.2.0.3 RAC(VCS)节点crash以及hang的问题分析

    昨天某个客户的一套双节RAC当中一个节点crash,同一时候最后导致另外一个节点也hang住,仅仅能shutdown abort. 且出现shutdown abort实例之后,还有部分进程无法通过ki ...

  7. 如何定位 golang 进程 hang 死的 bug

    之前在 golang 群里有人问过为什么程序会莫名其妙的 hang 死然后不再响应任何请求.单核 cpu 打满. 这个特征和我们公司的某个系统曾经遇到的情况很相似,内部经过了很长时间的定位分析总结,期 ...

  8. Oracle数据库shutdown immediate被hang住的几个原因

    实验操作环境:         操作系统:Red Hat Enterprise Linux ES release 4 (Nahant Update 6)                         ...

  9. 一则因为numa引发的mysqldump hang住

    新买的dell r430服务器,双CPU,64G内存,单CPU32g,swap 3G 出现故障现像:mysqldump时会hang住,innodb_buffer_pool_size        = ...

随机推荐

  1. 组件Newtonsoft.Json实现object2json转换

    很多情况下,我们需要把数据类型做一些转换,供其它外部的子系统调用. 最为典型的是生成json格式供javascript作调用. 现成的组件Newtonsoft.Json可以实现object2json之 ...

  2. ListActivity的使用

    Android中经常用到列表,ListActivity是实现列表的一种好方法. 使用ListActivity的方法,首先定义布局文件: <?xml version="1.0" ...

  3. 【Java每日一题】20161027

    package Oct2016; public class Ques1027 { public static void main(String[] args) { System.out.println ...

  4. themepark模板中奇特的编码

    编码问题虽然经常碰到,但通过编码来实现源代码加密的是第一次碰到.只能用神奇来形容. 而且研究了几个小时,没有想到解决办法.代码基本可以通过不断执行输出,但无法判断是何种编码.

  5. Java基础复习笔记系列 九 网络编程

    Java基础复习笔记系列之 网络编程 学习资料参考: 1.http://www.icoolxue.com/ 2. 1.网络编程的基础概念. TCP/IP协议:Socket编程:IP地址. 中国和美国之 ...

  6. 【FOL】第二周

    一直在忙其他事情,停了好久了.终于又可以开始做点东西了. 这周主要工作: 1.整理客户端代码,加入网络模块:fol.client.net. 2.写了个简单的版本服务端程序. 3.初步完成了自动更新功能 ...

  7. BaseActivity的抽取

    Activity有些公共部分,比如setContentView.Activity管理.初始化操作.联网操作.Activity跳转.关闭当前Activity.保存用户登录信息.读取用户登录信息等. 我们 ...

  8. Eclipse安装SVN插件及使用说明

    1.下载Eclipse,如果没有安装的请到这里下载安装:http://eclipse.org/downloads/ ,关于Eclipse的下载安装不再赘述. 2.下载SVN插件subclipse,安装 ...

  9. .Net中的并行编程-4.实现高性能异步队列

    上文<.Net中的并行编程-3.ConcurrentQueue实现与分析>分析了ConcurrentQueue的实现,本章就基于ConcurrentQueue实现一个高性能的异步队列,该队 ...

  10. jQuery cxScroll 间歇式无缝滚动

    版本: jQuery v1.7+ jQuery cxScroll v1.2.2 注意事项: 内部会自动创建 prev 及 next 切换按钮,也可以在外部直接创建,若外部已创建或设置prevBtn: ...