摘自http://www.cppblog.com/elva/archive/2010/08/02/121943.html
Linux下,多线程程序死循环问题调试
当你的软件在某个时刻停止服务,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 icdn
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 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 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
分享到:
相关推荐
基于Linux的程序可以利用各种工具和方法来检查是否存在死循环和其他运行时错误。下面将详细介绍如何进行这样的检测。 1. **GDB(GNU调试器)**: GDB是Linux下最常用的调试工具,它允许程序员在程序运行过程中设置...
【练习】:编写多线程程序,总结exit、return、pthread_exit各自退出效果。 return:返回到调用者那里去。 pthread_exit():将调用该函数的线程 exit: 将进程退出。 pthread_join函数 阻塞等待线程退出,获取...
- **死循环**:条件判断错误导致的无限循环。 - **条件分支错误**:错误的条件表达式导致程序流程不符合预期。 - **解决方法**: - 使用断言(assertion)进行中间结果验证。 - 单元测试验证程序功能。 #### 四、...
在多线程环境下,资源的管理和同步是关键问题。包括发消息互斥量、连接相关互斥量、连接回收队列相关互斥量等资源的初始化,以及epoll相关技术的使用,都说明了在高并发编程中需要特别注意资源竞争和同步问题。 8. ...
6. **并发与多线程**:为了增加游戏的视觉效果,可以考虑使用多线程,让不同的任务(如更新网格和绘制屏幕)同时进行。在Linux中,这需要用到`pthread`库。 7. **编译与调试**:了解如何使用`gcc`编译器进行编译和...
通过对以上数据的综合分析,最终定位到了问题的原因——代码中分配了固定的10KB缓冲区,在极端情况下该缓冲区被写满,导致程序进入死循环。修复方法很简单,只需调整缓冲区大小或者实现更为智能的缓冲机制即可。 ##...
9. **多线程编程**:pthread库提供了在Unix/Linux上进行多线程编程的接口,包括线程创建、同步(如互斥锁、条件变量)和通信。 10. **设备驱动编程**:对于更底层的编程,可以编写设备驱动程序与硬件直接交互。这...
在Linux操作系统中,同步与互斥是多线程和多进程编程中的重要概念,用于确保对共享资源的正确访问和管理。System V IPC(Interprocess Communication)提供了一组接口,其中包括信号量,来帮助实现这一目标。本...
1. **URL管理**:爬虫需要管理待爬取和已爬取的URL队列,防止重复抓取和死循环。这通常通过数据结构如链表或队列来实现。 2. **HTTP请求**:利用libcurl库发送GET或POST请求,获取网页内容。设置头信息、处理重定向...
修改BUG:高级表格在列类型为数值型时,添加新行且省略标题的情况下,会导致程序异常。 16. 修改BUG:数值计算支持库“大数.四舍五入()”命令在最高位进位时,会导致程序异常。 17. 修改BUG:办公组件支持库打印...
例如,在Python中,可以使用continue语句跳过当前循环迭代并继续下一次迭代,而在多线程环境下,我们可以唤醒被暂停的线程使其继续执行。 在这个压缩包文件中,有两个文件:"ImproveWaitbar.fig"和"ImproveWaitbar....
- **线程安全:** 多线程环境下,程序可以正确执行且不会导致数据不一致。 - **Servlet:** 默认情况下Servlet不是线程安全的,需要开发者自行保证。 **在Java程序中怎么保证多线程的运行安全** - 使用同步机制...
然而,过度优化可能导致代码碎片化,对于大规模程序,可能会增加内存碎片,影响多线程环境下的性能。 3. GCC -o2:在-o1的基础上,GCC -o2增加了更深入的优化,如使用寄存器存储更多变量以提高效率。寄存器是CPU...
4. **多线程支持**:GCC 4.4.7支持多线程编程,可以与POSIX线程库(pthread)良好配合,提供并发编程的能力。 5. **平台兼容性**:GCC广泛支持各种硬件架构和操作系统,4.4.7版本也不例外,可以在Linux、FreeBSD、...
7. **多线程支持**:对于支持多线程的处理器,编译器可能包含对线程安全性的考虑和优化。 8. **代码大小优化**:在保持性能的同时,尽可能减小生成代码的体积。 9. **兼容性**:确保编译器与各种第三方库和开发...
- windows下进入某些系统文件夹死循环bug解决 - tips 居中显示 - 任务栏标签选中问题:已经显示且为交点窗口 点击——隐藏;否则——显示,并且置为焦点窗口 - 拖入url ——oexe 新窗口打开 - 选中文件时,移动...
� 基于 QEMU 开发的模拟器调试手段不十分丰富,只支持通话、SMS等,速度慢。 � 暂不具备 Push Mail 和 Office(DataViz 、 QuickOffice 计划近期推出 ) 功能,目前主要面向的是普通消费 者 用户,对商业用户支持...
14. **Release版本问题检测**:使用内存检测工具(如Valgrind)检测内存泄漏,利用调试器检查段错误,分析CPU占用高的原因可能是死循环或资源竞争。 15. **C++拷贝构造函数与赋值运算符**:两者都是处理对象复制的...
- **URL管理**:爬虫需要跟踪已访问和待访问的URL,防止重复抓取和陷入死循环。 2. **C语言编程** - **基本语法**:SimSpider使用C语言编写,C语言是一种底层、高效的编程语言,适合处理大量数据和系统级编程。 ...
##### 7、多线程安全问题的解决方法 - **同步**:使用`synchronized`关键字。 - **并发工具类**:如`AtomicInteger`、`ConcurrentHashMap`等。 ##### 8、线程通信 线程之间可以通过`wait()`、`notify()`和`...