线程循环系统()和cout会破坏堆栈

时间:2014-05-31 04:14:14

标签: c++ linux multithreading segmentation-fault

运行以下代码的进程崩溃并出现Segmentation fault:

#include <stdlib.h>
#include <iostream>
#include <pthread.h>

void* f( void* )
{
   while( true )
   {
      // It crashes inside this call (with cerr, too).
      std::cout << 0;
   }
   return NULL;
}

int main()
{
   pthread_t t;
   pthread_create( &t, NULL, &f, NULL );

   while( true )
   {
      // It crashes with any script/app; true is just simple.
      system( "true" );
   }
   return 0;
}

它在几秒钟内崩溃了所有其他执行(输出有几千到几百的'0')。它使用上面的代码在cout << 0调用深度崩溃了一些函数。根据{{​​1}}中调用的额外函数或放在堆栈上的数据,它会在不同的地方崩溃。在gdb中,有时堆栈对函数调用的顺序没有意义。从此我推断堆栈已损坏。

我发现有一些problems with multi-threaded applications calling fork()(另见两条提到堆栈损坏的评论)。分析/克隆进程会复制文件描述符(如果它们未设置为f())。但是,没有明确创建的文件描述符。 (我尝试在FD_CLOEXECFD_CLOEXEC上设置fileno( stdout )而没有任何正面更改。)

即使没有明确的文件描述符,我也不能混合线程和fileno( stderr )?我是否只需要用等效功能替换fork()来电?或者内核中是否存在导致此崩溃的错误,并且已在2.6.30之后修复?

其他细节

我在ARM AT91处理器(armv5tejl)上运行它,使用Linux 2.6.30(我的特定外设集合的一些覆盖和补丁)用GCC 4.3.2编译。

system()

我曾[{1}}和Linux 2.6.30 #1 Thu May 29 15:43:04 CDT 2014 armv5tejl GNU/Linux 对其进行[交叉]编译,但没有那些仍然会崩溃:

-g

我还尝试了-O0标志:有时它会在arm-atmel-linux-gnueabi-g++ -o system_thread system_thread.cpp -lpthread 中崩溃,但有时其他函数指针或数据会被破坏并且之前会崩溃。

它加载的库(来自strace):

-fstack-protector-all

注意:由于它有时不会崩溃并且对__stack_chk_fail()没有真正的响应,我通常会在后台运行它:

libpthread.so.0
libstdc++.so.6
libm.so.6
libgcc_s.so.1
libc.so.6

我已经针对一些不同的体系结构和Linux内核版本编译了这个程序,但我还没有看到它在其他任何地方崩溃:

^C

编辑:请注意,在相同的架构(armv5tejl)上,它不会因Linux 3.10.29而崩溃。此外,在早期版本的“设备”(较旧的服务器和客户端应用程序)上运行时,它不会崩溃,具有相同版本的Linux - 2.6.30。因此,操作系统的环境会产生一些影响。

BusyBox v1.20.1提供了$ killall -9 system_thread; rm -f log; system_thread >log & Linux 3.10.29 #1 Wed Feb 12 17:12:39 CST 2014 armv5tejl GNU/Linux Linux 3.6.0-dirty #3 Wed May 28 13:53:56 CDT 2014 microblaze GNU/Linux Linux 3.13.0-27-generic #50-Ubuntu SMP Thu May 15 18:06:16 UTC 2014 x86_64 x86_64 GNU/Linux Linux 3.8.0-35-generic #50~precise1-Ubuntu SMP Wed Dec 4 17:25:51 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux 次来电。{/ p>

1 个答案:

答案 0 :(得分:2)

这在使用您提到的2.6.30内核的ARM处理器上是可重现的,但不在master中。我们可以使用git bisect来查找修复此错误的位置(大约需要16次迭代)。请注意,由于git bisect旨在找到回归,但在这种情况下,主人是好的&#34;但过去的版本很糟糕,&#34;我们需要reverse the meanings of "good" and "bad"

二分法发现的罪魁祸首是this commit,以修复用户空间数据损坏的实例&#34;涉及fork()。此症状与您描述的症状非常相似,并且还可能损坏堆栈外部的内存。将此提交和the required parent向后移植到2.6.30内核后,您发布的代码不再崩溃。

相关问题