strace 打印堆棧

平常初次定位問題時,我一般是先看看 api 調用,再不濟就多看看堆棧,如用 gdb 的commands 指令在 每次斷點時自動打印堆棧。

 

strace 有個實驗性的功能,在打印每個系統調用的同時打印當時的堆棧,有了堆棧簡直就是手握問題的鑰匙。

strace -h
...
  -k             obtain stack trace between each syscall
...

but,but,but,but,but,but,but,but,but,but,but,but,

公司中開發環境的centos linux 上自帶的 strace 沒有編譯對 -k 功能 的支持。只能自己從源代碼中編譯。

[strace-4.24]# ./configure --help
...
  --with-libdw            use libdw to implement stack tracing support

  --with-libunwind        use libunwind to implement stack tracing support
  --with-libiberty        use libiberty to demangle symbols in stack trace
...

首次編譯時,只加了 --with-libunwind ,--with-libunwind 與 --with-libdw 功能是同樣的,選其中一個就可以了,只是我對 libunwind 多點偏好而已。

CFLAGS="-O2 -fPIC" \
./configure \
  --prefix=/usr \
  --mandir=/usr/man \
  --with-libunwind

看看編譯後新的 strace -k 去trace mysqld 的打印:

# strace -f -y -k -p 18297

...
[pid 10719] getrusage(RUSAGE_SELF, {ru_utime={tv_sec=102, tv_usec=148630}, ru_stime={tv_sec=39, tv_usec=239462}, ...}) = 0
 > /usr/lib64/libc-2.17.so(getrusage+0x7) [0xf5057]
 > /usr/libexec/mysqld(_ZN16PROF_MEASUREMENTC1EP13QUERY_PROFILEPKc+0x15) [0x42e065]
 > /usr/libexec/mysqld(_ZN13QUERY_PROFILE10new_statusEPKcS1_S1_j+0x46) [0x42e2c6]
 > /usr/libexec/mysqld(_ZN9PROFILING20finish_current_queryEv+0x28) [0x42e598]
 > /usr/libexec/mysqld(_Z16dispatch_command19enum_server_commandP3THDPcj+0x4cc) [0x37a21c]
 > /usr/libexec/mysqld(_Z24do_handle_one_connectionP3THD+0x1c2) [0x42da22]
 > /usr/libexec/mysqld(handle_one_connection+0x4a) [0x42daca]
 > /usr/lib64/libpthread-2.17.so(start_thread+0xc5) [0x7e25]
 > /usr/lib64/libc-2.17.so(clone+0x6d) [0xfebad]
...

不錯了,可以啓用 -k 功能打印出堆棧,但對於 c++ 程序中的堆棧中的名字沒有做到 demangle ,像  _ZN16PROF_MEASUREMENTC1EP13QUERY_PROFILEPKc 這樣的名字,可以用下面命令看到 demangle 後的真正函數簽名

# c++filt _ZN16PROF_MEASUREMENTC1EP13QUERY_PROFILEPKc
PROF_MEASUREMENT::PROF_MEASUREMENT(QUERY_PROFILE*, char const*)

 

回來,再次 編譯 strace ,這次 加上 --with-libiberty

CFLAGS="-O2 -fPIC" \
./configure \
  --prefix=/usr \
  --mandir=/usr/man \
  --with-libunwind \
  --with-libiberty

.
.
.
checking whether to enable stack tracing support... yes, using libunwind
checking demangle.h usability... yes
checking demangle.h presence... yes
checking for demangle.h... yes
checking for cplus_demangle in -liberty... yes
checking libiberty/demangle.h usability... no
checking libiberty/demangle.h presence... no
checking for libiberty/demangle.h... no
configure: error: in `/tmp/strace-4.24':
configure: error: failed to find demangle.h
See `config.log' for more details

# echo $?
1

but, but, but, but, but, but, but, but, but, but, but, 

源碼中的編譯配置不正確,

怎麼回事,failed to find demangle.h  ???

再看上一句,真正找不到的是 checking libiberty/demangle.h presence... no

看了一下我係統中的頭文件

不對呀,這不是有 #include "libiberty.h" ,也有 cplus_demangle 等相關的 C++ demangle 函數。

再看一下源碼中的 編譯配置

好傢伙,它同時 檢查 demangle.h libiberty/demangle.h 這兩個頭文件存不存在,但上面  /usr/include/demangle.h 已經 include libiberty 相關的東西,由此看來這個 libiberty/demangle.h 是多餘的,把它刪除就可以了,而且我的centos 上安裝的 binutils 包中沒有

這麼看來 很舊以前 binutls 包可能有 libiberty/demangle.h 這個文件,但現在的新版本沒有了。

也可能由於 很多的 linux 發行版中的 strace 都不編譯支持 -k 功能,所以這個管理員只就沒有測試到 編譯-k 功能的編譯配置。

 

看看帶 demangle 特性的 -k 功能輸出:

# strace -f -y -k -p 18297

...
[pid  3792] getrusage(RUSAGE_SELF, {ru_utime={tv_sec=170, tv_usec=48683}, ru_stime={tv_sec=61, tv_usec=704638}, ...}) = 0
 > /usr/lib64/libc-2.17.so(getrusage+0x7) [0xf5057]
 > /usr/libexec/mysqld(PROF_MEASUREMENT::PROF_MEASUREMENT(QUERY_PROFILE*, char const*, char const*, char const*, unsigned int)+0x28) [0x42e0a8]
 > /usr/libexec/mysqld(QUERY_PROFILE::new_status(char const*, char const*, char const*, unsigned int)+0x148) [0x42e3c8]
 > /usr/libexec/mysqld(set_thd_proc_info+0x2e) [0x341ece]
 > /usr/libexec/mysqld(dispatch_command(enum_server_command, THD*, char*, unsigned int)+0x2c6) [0x37a016]
 > /usr/libexec/mysqld(do_handle_one_connection(THD*)+0x1c2) [0x42da22]
 > /usr/libexec/mysqld(handle_one_connection+0x4a) [0x42daca]
 > /usr/lib64/libpthread-2.17.so(start_thread+0xc5) [0x7e25]
 > /usr/lib64/libc-2.17.so(clone+0x6d) [0xfebad]
...

> /usr/libexec/mysqld(PROF_MEASUREMENT::PROF_MEASUREMENT(QUERY_PROFILE*, char const*, char const*, char const*, unsigned int)+0x28) 這樣的打印,好看極了

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章