2010-09-02 106 views
3

我正在開發一個項目,在那裏我需要獲取Java應用程序的本地堆棧。我能夠部分實現這一目標。感謝ptrace/multiprocessing和信號。多線程,帶停止和繼續信號的多處理

Linux上正常的java應用程序有最少14個線程數。在這14個我感興趣的只有主線程,我必須得到本地堆棧。考慮到這個目標,我已經開始了一個使用fork()的獨立進程,它監視主線程的本地堆棧。總之,我有兩個獨立的過程:一個正在被監控,另一個正在使用ptrace和信號處理進行監控。

步驟,在監測過程:

1)獲得主線程ID了其他14線程從過程。

2)PTRACE_ATTACH main_ID

3)ptrace_cont main_ID

連續循環開始

{

4)殺(main_ID,SIGSTOP)

5 )nanosleep並檢查/ proc/[p ID]/STAT DIR

6)ptrace_peekdata讀取堆棧和導航

7)ptrace_cont main_ID

8)了nanosleep和從/ proc/[PID]/STAT檢查狀態DIR

}

9)ptrace_detach main_ID

,這一完全給出了本地棧我信息不斷。但有時我遇到了一個問題。

問題:

當我送殺(main_ID,SIGSTOP)到主線程,從過程中其他線程獲得成品或採空狀態(T)和全過程塊。這不是一致性行爲,整個過程正確執行。我無法理解這種行爲,因爲我只是向主線程發出信號,爲什麼其他線程會受到影響? 有人可以幫我分析問題嗎?

我也嘗試在進程的所有線程上執行CONT和STOP信號,但問題仍然有時會出現。

感謝,桑迪普

+0

按照我迄今爲止的理解。 – 2010-10-26 10:42:40

+0

有一個默認信號處理程序對應於過程級別上的信號。當進程找到其任何子線程的信號時,各個信號正由任何一個線程處理,這取決於狀態,即忙或閒。這可能是導致我的結果不一致的原因。 – 2010-10-26 10:48:11

回答

0

假設你使用Linux,你應該使用tkill(2)或tgkill(2)而不是殺死(2)。在FreeBSD上,你應該使用SYS_thr_kill2系統調用。每tkill(2)用戶手冊:

tgkill()發送信號sig與在 線程組TGID線程ID TID線程。(相比之下,kill(2)只能用於將一個信號作爲一個整體發送給一個進程(即線程組),並且信號 將被傳遞到該進程內的任意線程中。)

忽略關於tkill(2)和朋友正在使用內部線程庫的內容,它通常被調試器/跟蹤器用來向特定線程發送信號。

此外,您應該使用waitpid(2)(或它的一些變體)等待線程接收SIGSTOP,而不是輪詢/ proc/[pid]/stat。這種方法將更加高效和響應更快。

最後,你似乎在做某種堆棧抽樣。您可能想要查看Google PerfTools,因爲這些工具包含一個正在進行堆棧抽樣的CPU採樣器,以獲取哪些功能消耗最多CPU時間的估計值。您可能可能重複使用這些工具已經完成的工作,因爲堆棧抽樣可能會非常棘手以提高可靠性。