Linux下,多線程程序死循環(huán)問題調(diào)試
當你的軟件在某個時刻停止服務(wù),CPU占用達到100%+,這種問題一個可能的原因是產(chǎn)生了死循環(huán),假設(shè)程序某處存在潛在的死循環(huán),并在某種條件下會引發(fā),本文以一個示例來定位出現(xiàn)死循環(huán)的位置。當程序某處存在死循環(huán),通常定位問題及縮小范圍的方法是,在可疑的代碼處加log,或者注釋掉可疑代碼,這對于容易重現(xiàn)問題的程序來說還好,但對于“偶爾”才會產(chǎn)生問題程序卻很難調(diào)試,因為我們很難重現(xiàn)程序故障。本文所述的調(diào)試過程正是在這種情況下,假設(shè)問題已經(jīng)出現(xiàn),我們要求環(huán)境保護現(xiàn)場,即出問題的程序還在運行中。
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 icdn
ovtsvn@ovtsvn:~/MASS4/src/icdn/src$ 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 18 0 325m 3980 2236 S 0 0.4 0:00.00 icdn
11070 ovtsvn 18 0 325m 3980 2236 S 0 0.4 0:00.00 icdn
11071 ovtsvn 22 0 325m 3980 2236 S 0 0.4 0:00.00 icdn
11072 ovtsvn 15 0 325m 3980 2236 R 0 0.4 0:00.00 icdn2.接下來,我們用gdb來attach目標進程
執(zhí)行: gdb icdn 11065
在gdb中,列出線程狀態(tài):
(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已經(jīng)列出了各線程正在執(zhí)行的函數(shù),我們需要更多信息,記住11073對應(yīng)的行首標號,這是gdb為線程分配的id,這里為2,然后執(zhí)行切換:
(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 現(xiàn)在我們定位到了出問題的代碼位置,這里的循環(huán)只用來演示的。
最后別忘了detach
posted on 2010-08-02 12:08 葉子 閱讀(7520) 評論(2) 編輯 收藏 引用 所屬分類: C\C++

