微信号:grzlwx

介绍:光荣之路官方资讯

Linux 多线程调试(内存占用、死循环、CPU占用率高……)

2015-06-30 22:34 光荣之路

你的软件在某个时刻停止服务,CPU占用达到100%+,这种问题一个可能的原因是产生了死循环,假设程序某处存在潜在的死循环,并在某种条件下会引发,本文以一个示例来定位出现死循环的位置。当程序某处存在死循环,通常定位问题及缩小范围的方法是,在可疑的代码处加log,或者注释掉可疑代码,这对于容易重现问题的程序来说还好,但对于“偶尔”才会产生问题程序却很难调试,因为我们很难重现程序故障。本文所述的调试过程正是在这种情况下,假设问题已经出现,我们要求环境保护现场,即出问题的程序还在运行中。

1.我们首先要知道是哪个线程出了问题:首先查一下出问题进程的pid,例如

ovtsvn@ovtsvn:~/MASS4/src/icdn/src$ ps -ef | grep icdn
ovtsvn 11065 1 50 11:57 ? 00:00:07 ./icdn
ovtsvn 11076 10971 0 11:57 pts/2 00:00:00 grep
ovtsvn@ovtsvn:~/MASS4/src/icdn/src$
ovtsvn@ovtsvn:~/MASS4/src/icdn/src$

然后top命令查看线程信息:top -H -p 11065

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
11073 ovtsvn 25 0 325m 3980 2236 R 100 0.4 1:40.84 icdn
11065 ovtsvn 18 0 325m 3980 2236 S 0 0.4 0:00.01 icdn
11066 ovtsvn 18 0 325m 3980 2236 S 0 0.4 0:00.00 icdn
11067 ovtsvn 15 0 325m 3980 2236 S 0 0.4 0:00.00 icdn
11068 ovtsvn 15 0 325m 3980 2236 S 0 0.4 0:00.00 icdn
11069 ovtsvn 180 325m 39802236 S 00.40:00.00 icdn
11070 ovtsvn 180 325m 39802236 S 00.40:00.00 icdn
11071 ovtsvn 220 325m 39802236 S 00.40:00.00 icdn
11072 ovtsvn 150 325m 39802236 R 00.40:00.00 icdn

从上面可以看出,出问题线程PID为11073


2.接下来,我们用gdb来attach目标进程执行: gdb icdn 11065在gdb中,列出线程状态:

(gdb) info threads

9 Thread 47056948181264 (LWP 11066) 0x00002acc4a3dec91 in nanosleep () from /lib/libc.so.6

8 Thread 47056956573968 (LWP 11067) 0x00002acc4a406fc2 in select () from /lib/libc.so.6

7 Thread 47056964966672 (LWP 11068) 0x00002acc4a3dec91 in nanosleep () from /lib/libc.so.6

6 Thread 47056973359376 (LWP 11069) 0x00002acc4a3dec91 in nanosleep () from /lib/libc.so.6

5 Thread 47056981752080 (LWP 11070) 0x00002acc4a3dec91 in nanosleep () from /lib/libc.so.6

4 Thread 47056990144784 (LWP 11071) 0x00002acc4a40e63c in recvfrom () from /lib/libc.so.6

3 Thread 47057194060048 (LWP 11072) 0x00002acc4a406fc2 in select () from /lib/libc.so.6

2 Thread 47057226893584 (LWP 11073) CSendFile::SendFile (this=0x2acc5d4aff40, pathname=@0x2acc5d4afee0) at ../src/csendfile.cpp:101

1 Thread 47056939784832 (LWP 11065) 0x00002acc4a3dec91 in nanosleep () from /lib/libc.so.6 (gdb)


gdb已经列出了各线程正在执行的函数,我们需要更多信息,记住11073对应的行首标号,这是gdb为线程分配的id,这里为2,然后执行切换:

(gdb) thread 2
[Switching to thread 2 (Thread 47057226893584 (LWP 11073))]#0 CSendFile::SendFile (this=0x2acc5d4aff40, pathname=@0x2acc5d4afee0) at ../src/csendfile.cpp:101 101 while(1)
(gdb)


bt一下:

(gdb) bt

#0 CSendFile::SendFile (this=0x2acc5d4aff40, pathname=@0x2acc5d4afee0) at ../src/csendfile.cpp:101

#1 0x000000000040592e in CIcdn::TaskThread (pParam=0x7fff617eafe0) at ../src/cicdn.cpp:128

#2 0x00002acc4a90b73a in start_thread () from /lib/libpthread.so.0

#3 0x00002acc4a40d6dd in clone () from /lib/libc.so.6

#4 0x0000000000000000 in ?? ()

来看一下101行的代码:

(gdb) l

96 }

97

98 int CSendFile::SendFile(const string& pathname)

99 {

100 int n;

101 while(1)

102 {

103 n++;

104 }

105 //read file and send


现在我们定位到了出问题的代码位置,这里的循环只用来演示的。最后别忘了detach()

调试完指定进程后,可以运行detach命令来让GDB释放该进程,该进程得以继续运行。当回车时,detach不会重复。当执行完detach后,进程和GDB不再相关,GDB可以attach其他进程。
(作者:星雨海蓝 来源:http://www.cnblogs.com/cy568searchx/p/3391790.html)

光荣之路软件测试培训

官网:http://www.gloryroad.cn/

微信公众号:gloryroadtrain

性能测试QQ群:415987441
软件测试招聘QQ群: 203715128
自动化3群QQ: 371211499


 
光荣之路 更多文章 今天晚上的 linux 公开课- Awk 编程 7月28日(今天)晚上的 linux 公开课- shell编程 8月4日(今天)晚上的 linux 公开课- shell编程 9月1日(本周一)晚8点半,光荣之路Web自动化系列基础课—javascript第二讲 推荐本好书《与机器赛跑》
猜您喜欢 R语言数据分析资料(免) 打码平台是如何运作的?再谈验证码安全 旅行,写作,编程。春节是不是也能这样过? 「企业上云」系列之开源数据库的现状 S2-029 Struts2 标签远程代码执行分析(含POC)