【发布时间】:2014-07-20 21:43:09
【问题描述】:
运行以下代码的进程因分段错误而崩溃:
#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 调用中的一些函数崩溃。根据在f() 中调用的额外函数或放入堆栈的数据,它会在不同的地方崩溃。在 gdb 中,有时堆栈对于函数调用的顺序没有意义。由此我推断堆栈已损坏。
我发现有一些problems with multi-threaded applications calling fork()(另见两个提到堆栈损坏的 cmets)。如果未将文件描述符设置为FD_CLOEXEC,则分叉/克隆进程会复制文件描述符。但是,没有明确创建的文件描述符。 (我尝试在fileno( stdout ) 和fileno( stderr ) 上设置FD_CLOEXEC,但没有积极变化。)
即使没有明确的文件描述符,我也不能混合线程和fork() 吗?我是否只需将system() 调用替换为等效功能?或者内核中是否存在导致此崩溃的错误并已在 2.6.30 之后修复?
其他详情
我在 ARM AT91 处理器 (armv5tejl) 上运行它,并使用 GCC 4.3.2 编译的 Linux 2.6.30(为我的特定外围设备集提供了一些覆盖和补丁)。
Linux 2.6.30 #1 Thu May 29 15:43:04 CDT 2014 armv5tejl GNU/Linux
我一直在 [cross] 使用 -g 和 -O0 编译它,但没有它们它仍然会崩溃:
arm-atmel-linux-gnueabi-g++ -o system_thread system_thread.cpp -lpthread
我也尝试过-fstack-protector-all 标志:有时它会在__stack_chk_fail() 中崩溃,但有时其他函数指针或数据会损坏并且它会更早崩溃。
它加载的库(来自 strace):
libpthread.so.0
libstdc++.so.6
libm.so.6
libgcc_s.so.1
libc.so.6
注意:由于它有时不会崩溃,也不会真正响应^C,因此我通常在后台运行它:
$ killall -9 system_thread; rm -f log; system_thread >log &
我已经为几个不同的架构和 Linux 内核版本编译了这个程序,但我没有看到它在其他任何地方崩溃:
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
编辑:请注意,在同一架构 (armv5tejl) 上,它不会在 Linux 3.10.29 中崩溃。此外,在具有相同版本的 Linux - 2.6.30 的我的“设备”(旧的服务器和客户端应用程序)的早期版本上运行时,它不会崩溃。所以操作系统的环境有一定的影响。
BusyBox v1.20.1 提供了sh,system() 调用。
【问题讨论】:
-
The
systemfunction is not thread-safe,但我不确定这是你的问题。 -
我认为由于您使用的是无限循环,这就是为什么它可能会执行到堆栈已满然后它会损坏,所以尽量不要使用无限循环。
-
顺便说一句,我无法重现崩溃。
-
无限循环通常会导致整个系统无响应。对于现在流行的抢占式多任务模型,无限循环通常会导致程序消耗所有可用的处理器时间,但通常可以由用户终止
-
@ali786 - 这些无限循环已从我的常规程序中简化,这是一个不断处理来自客户端的消息的服务器。通常循环正在等待套接字接收或信号量。这是仍然崩溃的最简单的代码。
标签: c++ linux multithreading segmentation-fault