运行以下代码的进程因分段错误而崩溃:
#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's)。它用上面的代码在cout << 0调用中崩溃了几个函数。根据调用的额外函数或放在f()堆栈上的数据,它会在不同的地方崩溃。在gdb中,有时堆栈对于函数调用的顺序没有意义。由此我推断堆栈被破坏了。
我发现有一些多线程应用程序调用fork()时出现的问题 (请参阅提到堆栈损坏的两个注释)。如果文件描述符未设置为FD_CLOEXEC,则对进程进行分叉/克隆。但是,没有显式创建的文件描述符。(我尝试将FD_CLOEXEC设置在fileno( stdout )和fileno( stderr )上,没有任何积极的变化。)
即使没有显式的文件描述符,我也不能混合线程和fork()吗?我是否只需要用等效的功能替换system()调用?或者,内核中是否存在导致此崩溃并在2.6.30之后修复的bug?
其他细节
我在用Linux2.6.30编译的ARM AT91处理器(armv5tejl)上运行它(带有特定外围设备的一些覆盖和补丁),用GCC 4.3.2编译。
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我也尝试过-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)上,它不会与Linux3.10.29崩溃。而且,在我的“设备”(旧的服务器和客户端应用程序)的早期版本上运行时,它不会崩溃,它具有相同版本的Linux2.6.30。因此,操作系统的环境有一定的影响。
BusyBox v1.20.1提供了system()调用的sh。
发布于 2014-06-05 21:39:45
这在使用您提到的2.6.30内核的ARM处理器上是可重复的,但在主处理器中则不然。我们可以使用git bisect找到这个bug的修复位置(大约需要16次迭代)。注意,由于git bisect的目的是查找回归,但在本例中,主版是“好的”,而过去的版本是“坏的”,所以我们需要颠倒“好”和“坏”的意思。
二分法发现的罪魁祸首是此承诺,它修复了包含fork()的“用户空间数据损坏的实例”。此症状与您描述的症状非常相似,还可能破坏堆栈外的内存。在将此提交和所需父级移植到2.6.30内核后,您发布的代码不再崩溃。
https://stackoverflow.com/questions/23966310
复制相似问题