2011-06-19 73 views
16

在Linux中,要獲得回溯,可以使用backtrace()庫調用,但它只返回當前線程的回溯。假如我知道它是TID(或pthread_t),並且我可以保證它睡覺,是否有任何方法可以獲得其他線程的回溯?獲取其他線程的回溯

似乎libunwind(http://www.nongnu.org/libunwind/)項目可以提供幫助。問題是CentOS不支持它,所以我不喜歡使用它。

還有其他想法嗎? 謝謝。

回答

7

藉助回溯信號處理可以解決您的目的。

我的意思是如果你有一個線程的PID,你可以爲該線程產生一個信號。並且在處理程序中您可以使用回溯。既然處理程序會在那個特殊的線程中執行,那麼回溯就會有你需要的輸出。

+1

這並不是我正在尋找的,但這是一個不錯的主意。我想我可以使用它。謝謝! –

+0

@Alexander是這個解決方案爲你工作時,malloc或免費的電話是調用堆棧..?並且你可以在這種情況下從信號處理程序調用backtrace()?我正在崩潰。 – sandeep

+0

最終,我決定使用libunwind。這個解決方案對於我的情況來說太複雜了,我決定放棄它。無論如何,如果你以某種方式使它工作,請在這裏發帖。 –

8

我自己實現了here

最初,我想實現類似建議here,即獲取線程的頂部幀指針和手動展開它(鏈接的源來自蘋果backtrace實現,因此可能是蘋果專用的,但想法是通用的)。

但是,爲了確保安全(上面的源代碼不是,甚至可能會被破壞),您必須在訪問堆棧時暫停該線程。我搜索了各種方式暫停線程,發現this,thisthis。基本上,沒有很好的方法。常見的黑客,也used by the Hotspot JAVA VM,是使用信號並通過pthread_kill發送自定義信號到您的線程。因此,無論如何我需要這樣的信號破解,我可以讓它更簡單一些,只需在目標線程中執行的被調用的信號處理程序中使用backtrace(同樣建議here by sandeep)。這基本上是我的實現正在做的。

如果您還希望打印回溯,即獲取一些有用的調試信息(函數名稱,源代碼文件名,源代碼行號......),請參閱here關於基於libbfd的擴展backtrace_symbols。或者只是看到源here

+1

阿爾伯特,我有一個場景,我需要從後臺線程獲取主線程的調用堆棧。背後的想法是,如果在UI線程中掛起超過2秒鐘,每200ms監視UI線程的後臺線程將收集調用堆棧。我想知道你的解決方案也可能解決這個問題?提前感謝。 –

+0

@ilkerAcar:是的,我的實現中的函數'int GetCallstack(ThreadId threadId,void ** buffer,int size)'可以從任何線程調用。只需傳遞主線程ID即可。 – Albert

+0

順便說一句,我也在做一些這樣的項目,參見'startMainLockDetector()'[這裏](https://github.com/albertz/openlierox/blob/0.59/src/MainLoop.cpp)。 – Albert

0

GDB提供這些設施進行調試多線程程序:

  • 自動的新主題
  • 「線程的線程ID」,命令線程
  • 「信息線」之間切換通知,查詢現有線程的命令
  • 'thread apply [thread-id-list] [all] args',將命令應用於線程列表的命令
  • 線程特定的斷點
  • 'set print thread-events',它控制線程啓動和退出時消息的打印。
  • 'set libthread-db-search-path path',如果默認選項與程序不兼容,它允許用戶指定使用哪個libthread_db。

所以剛剛通過cmd goto在GDB中需要線程:'thread thread-id'。 然後在該線程上下文中執行'bt'以打印線索回溯。