一次进程hang住问题分析。。。,hang..


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

$ pstree 18649

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

       └─{drcchk}

    回到问题本身,我用测试用例复现了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


UNIX 怎用命令hang住某个进程

假定进程号为 pid

kill -SIGSTOP pid 停止进程
kill -SIGCONT pid 继续运行被停住的进程。
 

找会分析进程的人

问:现在进程端口工具很多,什么要使用IceSword?
答:1、绝大多数所谓的进程工具都是利用Windows的Toolhlp32或psapi再或ZwQuerySystemInformation 系统调用(前二者最终也用到此调用)来编写,随便一个ApiHook就可轻轻松松干掉它们,更不用说一些内核级后门了;极少数工具利用内核线程调度结构来查询进程,这种方案需要硬编码,不仅不同版本系统不同,打个补丁也可能需要升级程序,并且现在有人也提出过防止此种查找的方法。而IceSword的进程查找核心态方案是目前独一无二的,并且充分考虑内核后门可能的隐藏手段,目前可以查出所有隐藏进程。
2、绝大多数工具查找进程路径名也是通过Toolhlp32、psapi,前者会调用RtlDebug***函数向目标注入远线程,后者会用调试api读取目标进程内存,本质上都是对PEB的枚举,通过修改PEB就轻易让这些工具找不到北了。而IceSword的核心态方案原原本本地将全路径展示,运行时剪切到其他路径也会随之显示。
3、进程dll模块与2的情况也是一样,利用PEB的其他工具会被轻易欺骗,而IceSword不会弄错(有极少数系统不支持,此时仍采用枚举PEB)。
4、IceSword的进程杀除强大且方便(当然也会有危险)。可轻易将选中的多个任意进程一并杀除。当然,说任意不确切,除去三个:idle进程、 System进程、csrss进程,原因就不详述了。其余进程可轻易杀死,当然有些进程(如winlogon)杀掉后系统就崩溃了。
5、对于端口工具,网上的确有很多,不过网上隐藏端口的方法也很多,那些方法对IceSword可是完全行不通的。其实本想带个防火墙动态查找,不过不想弄得太臃肿。这里的端口是指windows的IPv4 Tcpip协议栈所属的端口,第三方协议栈或IPv6栈不在此列。
6、先说这些了...

问:windows自带的服务工具强大且方便,IceSowrd有什么更好的特点呢?
答:因为比较懒,界面使用上的确没它来的好,不过IceSword的服务功能主要是查看木马服务的,使用还是很方便的。举个例子,顺便谈一类木马的查找:svchost是一些共享进程服务的宿主,有些木马就以dll存在,依靠svchost运作,如何找出它们呢?首先看进程一栏,发现 svchost过多,记住它们的pid,到服务一栏,就可找到pid对应的服务项,配合注册表查看它的dll文件路径(由服务项的第一栏所列名称到注册表的services子键下找对应名称的子键),根据它是不是惯常的服务项很容易发现异常项,剩下的工作就是停止任务或结束进程、删除文件、恢复注册表之类的了,当然过程中需要你对服务有一般的知识。

问:那么什么样的木马后门才会隐藏进程注册表文件的?用IceSword又如何查找呢?
答:比如近来很流行且开源(容易出变种)的hxdef就是这么一个后门。你用一些工具,***专家、***大师、***克星看看,能不能看到它的进程、注册项、服务以及目录文件,呵呵。用IceSword就很方便了,你直接就可在进程栏看到红色显示的hxdef100进程,同时也可以在服务栏中看到红色显示的服务项,顺便一说,在注册表和文件栏里你都可发现它们,若木马正在反向连接,你在端口栏也可看到。杀除它么,首先由进程栏得后门程序全路径,结束进程,将后门目录删除,删除注册表中的服务对应项...这里只是简单说说,请你自行学习如何有效利用IceSword吧。

问:“内核模块”是什么?
答:加载到系统内和空间的PE模块,主要是驱动程序*.sys,一般......余下全文>>
 

相关内容