<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>https://jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>https://jackxiang.com/post//</link>
<title><![CDATA[多线程调试必杀技 - GDB的non-stop模式]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[Unix/LinuxC技术]]></category>
<pubDate>Fri, 24 Apr 2015 09:30:04 +0000</pubDate> 
<guid>https://jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	背景：多进程有set follow-fork-mode=child，多线程怎么办呢?尤其是有那个时钟啥的，共享变量，这儿提供了一方法，我也没看懂，先放这儿。应该是gdb新的版本有这个功能。<br/><br/>作者：破砂锅<br/><br/>开源的GDB被广泛使用在Linux、OSX、Unix和各种嵌入式系统（例如手机），这次它又带给我们一个惊喜。<br/><br/>多线程调试之痛<br/>调试器（如VS2008和老版GDB）往往只支持all-stop模式，调试多线程程序时，如果某个线程断在一个断点上，你的调试器会让整个程序 freeze，直到你continue这个线程，程序中的其他线程才会继续运行。这个限制使得被调试的程序不能够像真实环境中那样运行--当某个线程断在一个断点上，让其他线程并行运行。<br/><br/>GDBv7.0引入的non-stop模式使得这个问题迎刃而解。在这个模式下，<br/><br/>当某个或多个线程断在一个断点上，其他线程仍会并行运行<br/>你可以选择某个被断的线程，并让它继续运行<br/>让我们想象一下，有了这个功能后<br/><br/>当其他线程断在断点上时，程序里的定时器线程可以正常的运行了，从而避免不必要得超时 <br/>当其他线程断在断点上时，程序里的watchdog线程可以正常的运行了，从而避免嵌入式硬件以为系统崩溃而重启<br/>可以控制多个线程运行的顺序，从而重现deadlock场景了。由于GDB可以用python脚本驱动调试，理论上可以对程序在不同的线程运行顺序下进行自动化测试。<br/>因此，non-stop模式理所当然成为多线程调试“必杀技”。这2009年下半年之后发布的Linux版本里都带有GDBv7.0之后的版本。很好奇，不知道VS2010里是不是也支持类似的调试模式了。<br/><br/>演示GDB的non-stop模式<br/>让破砂锅用一个C++小程序在Ubuntu Linux 09.10下demo这个必杀技。虽然我的demo使用命令行版gdb，如果你喜欢图形化的调试器，Eclipse2009年5月之后的版本可以轻松的调 用这个功能，详情参见Eclipse参见http://live.eclipse.org/node/723<br/><br/>1. 编译以下程序nonstop<br/><br/>1 // gdb non-stop mode demo<br/>2 // build instruction: g++ -g -o nonstop nonstop.cpp -lboost_thread<br/>3<br/>4 #include &lt;iostream&gt;<br/>5 #include &lt;boost/thread/thread.hpp&gt;<br/>6<br/>7 struct op<br/>8 &#123;<br/>9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; op(int id): m_id(id) &#123;&#125;<br/>10<br/>11 void operator()()<br/>12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#123;<br/>13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; m_id &lt;&lt; &quot; begin&quot; &lt;&lt; std::endl;<br/>14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; m_id &lt;&lt; &quot; end&quot; &lt;&lt; std::endl;<br/>15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>16<br/>17 int m_id;<br/>18 &#125;;<br/>19<br/>20 int main(int argc, char ** argv)<br/>21 &#123;<br/>22&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boost::thread t1(op(1)), t2(op(2)), t3(op(3));<br/>23&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t1.join(); t2.join(); t3.join();<br/>24 return 0;<br/>25 &#125;<br/>26<br/><br/>2. 把一下3行添加到~/.gdbinit来打开non-stop模式<br/><br/>set target-async 1<br/>set pagination off<br/>set non-stop on<br/><br/>3. 启动gdb,设断点,运行.可以看到主线程1是running,3个子线程都断在断点上,而不是只有一个子线程断在断点上.<br/><br/>~/devroot/nonstop$ gdb ./nonstop<br/>GNU gdb (GDB) 7.0-ubuntu<br/>Reading symbols from /home/frankwu/devroot/nonstop/nonstop...done.<br/>(gdb) break 14<br/>Breakpoint 1 at 0x402058: file nonstop.cpp, line 14.<br/>(gdb) break 24<br/>Breakpoint 3 at 0x401805: file nonstop.cpp, line 24.<br/>(gdb) run<br/>Starting program: /home/frankwu/devroot/nonstop/nonstop<br/>[Thread debugging using libthread_db enabled]<br/>[New Thread 0x7ffff6c89910 (LWP 2762)]<br/>[New Thread 0x7ffff6488910 (LWP 2763)]<br/>1 begin<br/>Breakpoint 1, op::operator() (this=0x605118) at nonstop.cpp:14<br/>14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout &lt;&lt; m_id &lt;&lt; &quot; end&quot; &lt;&lt; std::endl;<br/>2 begin<br/>Breakpoint 1, op::operator() (this=0x605388) at nonstop.cpp:14<br/>14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout &lt;&lt; m_id &lt;&lt; &quot; end&quot; &lt;&lt; std::endl;<br/>[New Thread 0x7ffff5c87910 (LWP 2764)]<br/>3 begin<br/>Breakpoint 1, op::operator() (this=0x605618) at nonstop.cpp:14<br/>14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;std::cout &lt;&lt; m_id &lt;&lt; &quot; end&quot; &lt;&lt; std::endl;<br/>(gdb) info threads<br/>4 Thread 0x7ffff5c87910 (LWP 2764)&nbsp;&nbsp;op::operator() (this=0x605618) at nonstop.cpp:14<br/>3 Thread 0x7ffff6488910 (LWP 2763)&nbsp;&nbsp;op::operator() (this=0x605388) at nonstop.cpp:14<br/>2 Thread 0x7ffff6c89910 (LWP 2762)&nbsp;&nbsp;op::operator() (this=0x605118) at nonstop.cpp:14<br/>* 1 Thread 0x7ffff7fe3710 (LWP 2759)&nbsp;&nbsp;(running)<br/><br/>4. 让线程3继续运行,注意我顾意把主线程1也continue,这是我发现的workaround,否则gdb不能切回thread 1.<br/><br/>(gdb) thread apply 3 1 continue<br/>Thread 3 (Thread 0x7ffff6488910 (LWP 2763)):<br/>Continuing.<br/>Thread 1 (Thread 0x7ffff7fe3710 (LWP 2759)):<br/>Continuing.<br/>Cannot execute this command while the selected thread is running.<br/>2 end<br/>[Thread 0x7ffff6488910 (LWP 2763) exited]<br/>warning: Unknown thread 3.<br/>Thread 1 (Thread 0x7ffff7fe3710 (LWP 2759)):<br/>Continuing.<br/>Cannot execute this command while the selected thread is running.<br/>(gdb) info threads<br/>4 Thread 0x7ffff5c87910 (LWP 2764)&nbsp;&nbsp;op::operator() (this=0x605618) at nonstop.cpp:14<br/>2 Thread 0x7ffff6c89910 (LWP 2762)&nbsp;&nbsp;op::operator() (this=0x605118) at nonstop.cpp:14<br/>* 1 Thread 0x7ffff7fe3710 (LWP 2759)&nbsp;&nbsp;(running)<br/><br/>5. 让另外两个线程继续运行而结束,主线程断在第24行,最后结束.<br/><br/>(gdb) thread apply 4 2 1 continue<br/>Thread 4 (Thread 0x7ffff5c87910 (LWP 2764)):<br/>Continuing.<br/>Thread 2 (Thread 0x7ffff6c89910 (LWP 2762)):<br/>Continuing.<br/>Thread 1 (Thread 0x7ffff7fe3710 (LWP 2759)):<br/>Continuing.<br/>Cannot execute this command while the selected thread is running.<br/>3 end<br/>1 end<br/>[Thread 0x7ffff5c87910 (LWP 2764) exited]<br/>[Thread 0x7ffff6c89910 (LWP 2762) exited]<br/>Breakpoint 3, main (argc=1, argv=0x7fffffffe348) at nonstop.cpp:24<br/>24&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/>(gdb) continue<br/>Thread 1 (Thread 0x7ffff7fe3710 (LWP 2759)):<br/>Continuing.<br/>Program exited normally.<br/><br/>参考资料<br/>Debugging with GDB<br/><br/>Reverse Debugging, Multi-Process and Non-Stop Debugging Come to the CDT<br/><br/>摘自：http://www.cnblogs.com/dongzhiquan/archive/2011/07/09/2101578.html<br/>一个 pthread_cancel 引起的线程死锁【整理转载】：<br/>http://www.cnblogs.com/mydomain/archive/2011/08/15/2139830.html
]]>
</description>
</item><item>
<link>https://jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] 多线程调试必杀技 - GDB的non-stop模式]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>https://jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>