qsort多线程下core dump分析
来源:互联网 发布:淘宝分期买手机靠谱吗 编辑:程序博客网 时间:2024/06/06 03:48
Glibc 2.9.93 qsort多线程下core dump分析
本文转自:http://www.youalab.com/?p=72
Posted on2010/09/19byyouaadmin
1 问题:
一个C实现的32位多线程服务在启动时core dump. 该服务运行了一年多,而此问题仅出现了一次,是一个比较难复现的问题。 出core的位置
在C库的qsort函数,信号是signal 8(算术错).
2 定位:
core的栈的结构如下:
#0 0x4202a801 in qsort () from /lib/i686/libc.so.6
#1 0x0804e74e in getFRes (databuf=0x406697fc) at fs.cpp:128
#2 0x0804ea74 in adjustOrder (databuf=0x406697fc) at fs.cpp:233
#3 0x0804e553 in Search (databuf=0x406697fc) at fs.cpp:66
#4 0x0804e4b8 in getBResponse (databuf=0x406697fc) at fs.cpp:29
#5 0x0804c559 in getResponse (databuf=0x406697fc) at fs.cpp:283
#6 0x0804c292 in thread_main (arg=0x1) at fs.cpp:222
#7 0x40020941 in pthread_start_thread () from /lib/i686/libpthread.so.0
可以先通过GDB的命令查看出core的汇编指令。当程序core时,$eip保存了当时程序运行指令地址。通过x /i 命令可以将内存以汇编指令的
方式查看。 这样就可以得到core dump时运行的汇编指令。如下:
(gdb) x /i $eip
0x4202a801 <qsort+65>: divl 0x724(%ebx)
按汇编看,应该是除法指令出问题,一般觉得会是除数为0之类的错误 由于glibc是开源的,可以查看一下qsort原代码,此处要注意版本问
题,要下相同的版本才能方便问题定位。不同linux发行版带的glibc的版本可能是不同的,而且系统维护人员也可能升级过相关的库。 通过以
下几个命令可以查看系统的glibc版本。
$ ldd ./bin/fras libpthread.so.0 =>/lib/i686/libpthread.so.0 (0x4001a000)
libcrypto.so.2 =>/lib/libcrypto.so.2 (0x4004b000) libc.so.6 =>/lib/i686/libc.so.6 (0x42000000)
libdl.so.2 =>/lib/libdl.so.2 (0x4011f000)/lib/ld-linux.so.2 =>/lib/ld-linux.so.2 (0x40000000)
/lib/i686/libc.so.6 (0x42000000) libdl.so.2 =>/lib/libdl.so.2 (0x4011f000) /lib/ld-linux.so.2 =>/lib/ld-linux.so.2 (0x40000000)
$ /lib/i686/libc.so.6 -v GNU C Library development release version 2.2.93 , by Roland McGrath et al. Copyright (C)1992-2001, 2002
Free Software Foundation, Inc. This is free software; see the sourcefor copying conditions. There is NO warranty; not even for
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiled by GNU CC version 3.2 20020903(Red Hat Linux 8.03.2-7)
. Compiled on a Linux 2.4.9-9 system on 2002-09-05. Available extensions:
下载glibc 2.2.93版本,查看其qsort实现,以下为简化版的原代码
void qsort (void*b, size_t n, size_t s, __compar_fn_t cmp)
{
const size_t size = n * s;
if(size < 1024)
{
void*buf = __alloca (size);
/* The temporary array is small, so put it on the stack. */
msort_with_tmp (b, n, s, cmp, buf);
}
else
{
staticlong int phys_pages;
static int pagesize;
if(phys_pages ==0)
{
phys_pages = __sysconf (_SC_PHYS_PAGES);
if(phys_pages ==-1)
phys_pages = (longint)(~0ul >>1);
phys_pages /=4;
pagesize = __sysconf (_SC_PAGESIZE);
}
if(size / pagesize > phys_pages)
_quicksort (b, n, s, cmp);
......
}
}
根据错误类型(除法错),可以看到出问题的指令刚好对应代码中黑体部分(size / pagesize > phys_pages); 接下来的问题就相对简单了,程
序中有两个static变量如下
staticlongint phys_pages;
static int pagesize;
在多线程情况下,线程A先运行到第一处黑体代码,静态变量 phys_pages 的值将被修改,即不为0,而pagesize未被赋值. 若此时发生线程
切换,线程B开始运行,到分支判断处phys_pages已不为0,所以else条件将被执行,而此时由于pagesize变量尚未被赋 值,结果 (size /
pagesize)这一步就发生除0错误了。所以,core dump时的表现就是signal 8即算术错。
3 解决: 可见,该glibc版本的qsort函数不是多线程安全的。 在不修改glibc的基础上,可以考虑绕过此问题的办法:
在主程序(线程未启动时)中先调用qsort一次,为static变量赋上值。
需要注意的:初始化时,n*s必须大于1024,否则pagesize没进行初始化。
–EnD–
本文转自:http://www.youalab.com/?p=72
Posted on2010/09/19byyouaadmin
1 问题:
一个C实现的32位多线程服务在启动时core dump. 该服务运行了一年多,而此问题仅出现了一次,是一个比较难复现的问题。 出core的位置
在C库的qsort函数,信号是signal 8(算术错).
2 定位:
core的栈的结构如下:
#0 0x4202a801 in qsort () from /lib/i686/libc.so.6
#1 0x0804e74e in getFRes (databuf=0x406697fc) at fs.cpp:128
#2 0x0804ea74 in adjustOrder (databuf=0x406697fc) at fs.cpp:233
#3 0x0804e553 in Search (databuf=0x406697fc) at fs.cpp:66
#4 0x0804e4b8 in getBResponse (databuf=0x406697fc) at fs.cpp:29
#5 0x0804c559 in getResponse (databuf=0x406697fc) at fs.cpp:283
#6 0x0804c292 in thread_main (arg=0x1) at fs.cpp:222
#7 0x40020941 in pthread_start_thread () from /lib/i686/libpthread.so.0
可以先通过GDB的命令查看出core的汇编指令。当程序core时,$eip保存了当时程序运行指令地址。通过x /i 命令可以将内存以汇编指令的
方式查看。 这样就可以得到core dump时运行的汇编指令。如下:
(gdb) x /i $eip
0x4202a801 <qsort+65>: divl 0x724(%ebx)
按汇编看,应该是除法指令出问题,一般觉得会是除数为0之类的错误 由于glibc是开源的,可以查看一下qsort原代码,此处要注意版本问
题,要下相同的版本才能方便问题定位。不同linux发行版带的glibc的版本可能是不同的,而且系统维护人员也可能升级过相关的库。 通过以
下几个命令可以查看系统的glibc版本。
$ ldd ./bin/fras libpthread.so.0 =>/lib/i686/libpthread.so.0 (0x4001a000)
libcrypto.so.2 =>/lib/libcrypto.so.2 (0x4004b000) libc.so.6 =>/lib/i686/libc.so.6 (0x42000000)
libdl.so.2 =>/lib/libdl.so.2 (0x4011f000)/lib/ld-linux.so.2 =>/lib/ld-linux.so.2 (0x40000000)
/lib/i686/libc.so.6 (0x42000000) libdl.so.2 =>/lib/libdl.so.2 (0x4011f000) /lib/ld-linux.so.2 =>/lib/ld-linux.so.2 (0x40000000)
$ /lib/i686/libc.so.6 -v GNU C Library development release version 2.2.93 , by Roland McGrath et al. Copyright (C)1992-2001, 2002
Free Software Foundation, Inc. This is free software; see the sourcefor copying conditions. There is NO warranty; not even for
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiled by GNU CC version 3.2 20020903(Red Hat Linux 8.03.2-7)
. Compiled on a Linux 2.4.9-9 system on 2002-09-05. Available extensions:
下载glibc 2.2.93版本,查看其qsort实现,以下为简化版的原代码
void qsort (void*b, size_t n, size_t s, __compar_fn_t cmp)
{
const size_t size = n * s;
if(size < 1024)
{
void*buf = __alloca (size);
/* The temporary array is small, so put it on the stack. */
msort_with_tmp (b, n, s, cmp, buf);
}
else
{
staticlong int phys_pages;
static int pagesize;
if(phys_pages ==0)
{
phys_pages = __sysconf (_SC_PHYS_PAGES);
if(phys_pages ==-1)
phys_pages = (longint)(~0ul >>1);
phys_pages /=4;
pagesize = __sysconf (_SC_PAGESIZE);
}
if(size / pagesize > phys_pages)
_quicksort (b, n, s, cmp);
......
}
}
根据错误类型(除法错),可以看到出问题的指令刚好对应代码中黑体部分(size / pagesize > phys_pages); 接下来的问题就相对简单了,程
序中有两个static变量如下
staticlongint phys_pages;
static int pagesize;
在多线程情况下,线程A先运行到第一处黑体代码,静态变量 phys_pages 的值将被修改,即不为0,而pagesize未被赋值. 若此时发生线程
切换,线程B开始运行,到分支判断处phys_pages已不为0,所以else条件将被执行,而此时由于pagesize变量尚未被赋 值,结果 (size /
pagesize)这一步就发生除0错误了。所以,core dump时的表现就是signal 8即算术错。
3 解决: 可见,该glibc版本的qsort函数不是多线程安全的。 在不修改glibc的基础上,可以考虑绕过此问题的办法:
在主程序(线程未启动时)中先调用qsort一次,为static变量赋上值。
需要注意的:初始化时,n*s必须大于1024,否则pagesize没进行初始化。
–EnD–
- qsort多线程下core dump分析
- Glibc中std::qsort在多线程下出core原因分析及解决
- AIX 下的 core dump 分析入门
- AIX 下的 core dump 分析入门
- AIX 下的 core dump 分析入门
- AIX 下的 core dump 分析入门
- AIX 下的 core dump 分析入门
- AIX 下的 core dump 分析入门
- AIX 下的 core dump 分析入门
- AIX 下的 core dump 分析入门
- AIX 下的 core dump 分析入门
- AIX Core Dump 分析
- Core dump 分析--AIX
- core dump 故障分析
- Core Dump流程分析
- linux下core dump
- Solaris下core dump文件的分析方法
- aix core dump定位分析
- linux下多线程 之 pthread_detach(pthread_self())
- Mac 系统 Versions配置(版本控制工具)
- 挖掘思路法
- 如何在15分钟内掌握JavaScript面向对象编程
- 时钟系统
- qsort多线程下core dump分析
- Jquery选择器总结
- Java RPC通信机制之RMI
- 查找linux系统下的端口被占用进程的两种方法
- iphone模拟器目录
- java中main函数中的变量定义及其使用
- TeX-标题和章节
- 建立一个php页面,显示php的一些功能,并加以说明(php上传文件)
- T(n) = 25T(n/5)+n^2的时间复杂度