2010-06-09 26 views
3

我有基於IO::Async的Perl程序,它有時會在幾小時/幾天後退出,而不會打印任何錯誤消息。 dmesg/var/log也沒有。 STDOUT/STDERR都是autoflush(1),所以數據不應該在緩衝區中丟失。它實際上並沒有從IO::Async::Loop->loop_forever退出 - 我只是爲了確保永遠不會被觸發而放在那裏。如何調試突然退出的Perl程序?

現在,一種方法是繼續用更多的印刷品來刻畫程序,並希望其中一個給我一些線索。有沒有更好的方法來獲取信息在程序中發生了什麼,使程序退出/靜默崩潰?

+3

我不明白爲什麼這應該是社區wiki'd。 – Zaid 2010-06-09 06:30:26

回答

6

我用過的一個技巧是運行straceltrace(或附加到使用strace的過程)下的程序。當然這是在Linux下。在其他操作系統下,您可以使用ktracedtrace或其他適當的操作系統。

我用過的程序只有幾天或一週纔會出現稀疏問題,然後在數百個系統中只有很少的一部分是把我的跟蹤器的輸出指向FIFO,並且有一個自定義程序只保留10K (在SIGPIPE和SIGHUP上用一個處理程序將當前緩衝區內容轉儲到一個文件中)(這是一個簡單的程序,但我沒有一個方便的副本,我不打算重寫它今天晚上;我的副本是爲內部使用,並由前僱主擁有)

環形緩衝區允許程序無限期運行,擔心繫統運行磁盤空間不足......我們通常只需要幾百,甚至有幾千行這樣的痕跡。

+0

它在Linux上。不會將可怕的事情拖垮/追蹤緩慢的事情嗎?這可能是一個問題,因爲發生崩潰需要數小時或數天。 我會很樂意嘗試。做這樣一個strace環緩衝區最簡單的方法是什麼? – taw 2010-06-11 17:40:00

+0

@taw:strace不會明顯減慢大部分程序。對於大多數程序來說,系統調用處理開銷的一小部分;對於另一個Perl和大多數語言通常只使用一個CPU(當然,每個進程)。在多核或超線程系統(現在幾乎所有這些系統)中,都會留下足夠的CPU馬力來處理strace進程。 自然ltrace更加密集(它通過將自己插入動態鏈接來掛鉤到所有正常動態調度函數的調用路徑中)。通常還是可以的。 – 2010-06-12 21:20:50

+0

@taw:關於環形緩衝區:我是用Python編寫的,類似的可以在幾十行Perl中刪除,或者更少。你定義一個包含n個元素的列表/數組(在Python中初始化爲「None」或Perl中的undef引用)。然後,在讀取它們時,保留一個簡單的行計數器,並且始終用剛剛讀取的行替換陣列中的n%計數器(模數)。因此,n%counter +1始終是環形緩衝區中最早的行(或尚未循環的其中一個undef refs)。 – 2010-06-12 21:24:18

3

如果你正在捕獲STDERR,你可以啓動該程序爲perl -MCarp::Always foo_progCarp::Always強制堆棧跟蹤所有錯誤。

+0

我會試試。 一個非常令人不安的事情是,在大約100次的1次崩潰中,我得到了glibc malloc池內存損壞錯誤,這表明潛在的原因可能是許多庫程序使用中的一個二進制錯誤,並且它將更加困難發現一個純粹的Perl問題將會是。 – taw 2010-06-11 17:42:17

+0

這很糟糕。它看起來像你在一個'有趣'的時間。 – daotoad 2010-06-11 17:46:40

0

沒有任何錯誤信息的突然退出可能是SIGPIPE。傳統SIGPIPE是用來阻止事情像cat命令下面的管道:

cat file | head -10 

它通常不會導致任何東西被打印或者通過libcperl指示發生了什麼事。

由於在IO::Async基於程序你不想在SIGPIPE默默退出,我的建議是把程序中某個位置的主文件中的行類似

$SIG{PIPE} = sub { die "Aborting on SIGPIPE\n" }; 

這將在至少提醒你這個事實。如果您使用Carp::croak而不使用\n,那麼您甚至可能很幸運地得到syswrite等的文件/行號......導致SIGPIPE