RHEL环境下pstack无法打印函数调用栈问题求助
我在两台RHEL机器上使用pstack工具查看应用程序的函数调用栈时遇到了不一致的情况:
- 其中一台机器运行
pstack正常,输出完整的线程调用栈:
[root@civ4cez191 bin]# pstack 22947 Thread 2 (Thread 0x7f63cbe7d700 (LWP 22949)): #0 0x0000003c3640f0cd in pause () from /lib64/libpthread.so.0 #1 0x0000000000485a78 in _signalWaitThread(void*) () #2 0x0000003c36407aa1 in start_thread () from /lib64/libpthread.so.0 #3 0x0000003c360e8aad in clone () from /lib64/libc.so.6 Thread 1 (Thread 0x7f63d2d07700 (LWP 22947)): #0 0x0000003c360e1523 in select () from /lib64/libc.so.6 #1 0x00000000004ccc36 in TFDSETSelect(void*, void*, int) () #2 0x00000000004cb50f in SvrInit1(unsigned int (*)(void*, void**), unsigned int (*)(void*, void*, void**, unsigned int*), void (*)(void*), unsigned int (*)(unsigned short, unsigned short), void (*)(unsigned short, unsigned short), void (*)(unsigned short, unsigned short), unsigned short, unsigned char, unsigned short, unsigned char) () #3 0x00000000004259f0 in main ()
- 另一台机器的
pstack仅能打印线程名称,没有调用栈信息:
[root@civ4cez194 bin]# pstack 12672 Thread 7 (Thread 0x7f01892e2700 (LWP 12674)): Thread 6 (Thread 0x7f0188aa0700 (LWP 12743)): Thread 5 (Thread 0x7f0188a1e700 (LWP 7090)): Thread 4 (Thread 0x7f0188a5f700 (LWP 7127)): Thread 3 (Thread 0x7f01889dd700 (LWP 7178)): Thread 2 (Thread 0x7f0188ae1700 (LWP 7235)): Thread 1 (Thread 0x7f0193ca0740 (LWP 12672)):
我曾查找相关资料,得到以下提示:
要导出线程信息,必须使用支持调试的LinuxThreads版libpthread.so库。(可通过对pthreads库执行nm(1)命令,确认是否定义了__pthread_threads_debug符号。新版NPTL libpthread.so库不支持线程信息导出。)
但我对两台机器的/lib64/libpthread.so.0执行nm命令后,均发现存在__pthread_debug符号,目前仍无法解决问题,特此寻求帮助。
1. 检查应用程序是否带有调试符号
pstack依赖应用程序的调试符号来解析函数调用栈,如果目标程序在编译时没有添加-g参数生成调试符号,或者被strip工具移除了符号信息,就可能无法输出完整的调用栈。可以用以下命令检查:
file /path/to/your/application
如果输出中包含stripped字样,说明符号已被移除,需要使用带有调试符号的程序版本。
2. 确认pstack工具本身的版本差异
两台机器的pstack可能不是同一个版本,不同版本的pstack对NPTL线程的支持程度不同。可以执行以下命令查看版本:
pstack --version
如果版本不一致,可以尝试在有问题的机器上替换为正常机器上的pstack版本,或者安装最新版本的procps-ng包(pstack通常属于这个包)。
3. 检查核心转储限制与权限
有时候,pstack需要生成临时的核心转储来获取栈信息,如果系统的核心转储限制被设置为0,或者当前用户没有权限生成核心转储,就会导致无法获取栈信息。可以用以下命令检查:
ulimit -c
如果输出为0,执行ulimit -c unlimited临时开启核心转储,然后重新运行pstack试试。另外,也要确保应用程序的运行目录有写入权限。
4. 验证libpthread的实际版本与类型
虽然你已经确认了__pthread_debug符号存在,但可能两台机器的libpthread实际类型不同(比如一台是LinuxThreads,另一台是NPTL)。可以用以下命令查看:
getconf GNU_LIBPTHREAD_VERSION
这个命令会输出当前系统使用的线程库版本,比如NPTL 2.17或者LinuxThreads 0.10。如果有问题的机器是NPTL,即使有__pthread_debug符号,也可能存在兼容性问题,这时候可以尝试使用gdb来替代pstack获取栈信息:
gdb -p 12672 -ex "thread apply all bt" -ex quit
这个命令会输出所有线程的调用栈,效果和pstack类似,且对NPTL的支持更好。
5. 检查系统的调试包是否安装
RHEL系统中,部分库的调试符号需要单独安装对应的-debuginfo包,比如glibc-debuginfo和glibc-debuginfo-common。如果缺少这些包,pstack可能无法解析系统库(比如libpthread.so.0、libc.so.6)的函数信息。可以用以下命令安装:
yum install glibc-debuginfo glibc-debuginfo-common
安装完成后重新运行pstack试试。
内容的提问来源于stack exchange,提问作者Gaurav

