2012-04-29 8 views
4

私は、perlプロセスがハングする状況を再現するのが非常に難しいです。私はどこに掛けられているのか分かりません。 ps ax | grep <process name>は、私が理解しているように、睡眠中の素敵な優先順位で走っていることを意味するSNとしてstatの列を示しています。perlスクリプト(Linuxプロセス)がハングしている場所を見つける方法

私はスクリプトを調べましたが(そこには大量のコードがありますが)、数秒以上続く特定の睡眠を見ることはできません(このプロセスは1日以上寝ていました)。

条件が再現されない可能性があるため、Perlスクリプトを再起動してログを追加することはできません。私はstraceを試みるが、より良い仕組み

+0

[実行中のPerlプロセスにデバッガを接続するにはどうすればいいですか?](http://stackoverflow.com/questions/8836711/how-can-i-attach-a-debugger-to-a-running -perl-process) – zoul

+0

応答をありがとう。私のクエリは、おそらくより広い範囲でです。私は、Perlプロセスにデバッガを接続する必要がないソリューションを使っても大丈夫です。例えば私はps ax + topがプロセスがタイトループではないことを私に教えてくれました。 – doon

答えて

4

可能な方法の1つは、gdbです。

まず、perlインタープリタのデバッグシンボルが必要です。例えば、私のDebianシステムでは、このためにperl-debugパッケージをインストールしなければなりませんでした。インストール後に/usr/lib/debug/usr/bin/perlがある場合は、後でgdbに渡します。元のスタックされたPerlスクリプトは、新しくインストールされたデバッグバージョンではなく、/usr/bin/perlを使用して開始されています。

この例のために、のは、このPerlスクリプトを実行してみましょう:今すぐにgdbを起動してみましょう

$ ./test.pl 
pid: 15764 
line 9 
line 10 
line 9 
line 10 
^C 

:我々はそれを実行すると

$ cat test.pl 
#! /usr/bin/perl 

use strict; 
use warnings; 

print "pid: ", $$, "\n"; 

while (1) { 
    print "line ", __LINE__, "\n"; sleep 1; 
    print "line ", __LINE__, "\n"; sleep 1; 
} 

、我々のような出力が得られます。今実行しているtest.plによって印刷されたPIDを使用してください。原因のperlインタプリタにGDBを取り付けるには、perlのを止めます、ところで

$ gdb /usr/lib/debug/usr/bin/perl 15809 
[snip] 
(gdb) 

$ ./test.pl 
pid: 15809 
line 9 
line 10 
[snip] 
line 9 
line 10 
line 9 
[no further output] 

を我々はいくつかの初期情報( "からシンボルを読む...")の後にプロンプ​​トを取得しますそれでは、バックトレースのために戻っGDBに取得してみましょう:それはそうだったよう

(gdb) backtrace 
#0 0x00007fd5b4479830 in __nanosleep_nocancel() at ../sysdeps/unix/syscall-template.S:82 
#1 0x00007fd5b44796c0 in __sleep (seconds=<optimized out>) at ../sysdeps/unix/sysv/linux/sleep.c:138 
#2 0x00007fd5b4efc1e2 in Perl_pp_sleep (my_perl=0x1a91010) at pp_sys.c:4586 
#3 0x00007fd5b4ea89b6 in Perl_runops_standard (my_perl=0x1a91010) at run.c:41 
#4 0x00007fd5b4e4a585 in S_run_body (oldscope=1, my_perl=0x1a91010) at perl.c:2350 
#5 perl_run (my_perl=0x1a91010) at perl.c:2268 
#6 0x0000000000400f89 in main (argc=2, argv=0x7fff4de87628, env=0x7fff4de87640) at perlmain.c:120 

、perlは)(睡眠の途中で停止することが起こりました。しかし、どちら?

ここで、現在実行中の(Perl)ソースファイルと行に関するperlの内部情報をどこで探すかを知る必要があります。もともと私はいくつかの関連情報を見つけたin the doumentation of mod_perl。そこにcurinfoマクロを探します。

(gdb) p my_perl->Icurcop->cop_file 
$1 = 0x1abd810 "./test.pl" 
(gdb) p my_perl->Icurcop->cop_line 
$2 = 9 

私たちはtest.plの9行目にあります。スクリプトの出力に基づいて期待通りです。

リンクされたドキュメントには、スレッド/非スレッドperlバイナリ(上記の例はスレッドperl、v5.14.2)の違いがいくつか記載されています。 my_perl->Icurcopの名前で探しているものが見つかりましたが、それはmy_perl->Tcurcopについて話しているので、少し古くなっています。現時点では、なぜこの名前が変更されたのかを知るために、perlの内部について十分な知識はありません。

こちらがお役に立てば幸いです。

1

がある場合、私はあなたがスクリプトを再起動することができないと言う知っているが、あなたはではなくログインするよりも、一度それを再起動するのですか場合、信号を使用してみてください不思議ことができます::のStackTraceまたは類似次回にはUSR2でプロセスにヒットし、スタックトレースダンプを取得できるようになります。

関連する問題