4

perl プロセスがハングする状態を再現するのは非常に困難です。どこに吊るされているかわかりません。ps ax | grep <process name>統計列を SN として表示します。これは、スリープ中であり、適切な優先度で実行されていることを意味します。

スクリプトを調べました (そこには大量のコードがあります) が、数秒以上続く特定のスリープは見当たりません (このプロセスは 1 日以上スリープ状態になっています)。

状態が再現されない可能性があるため、再起動して Perl スクリプトにログを追加することができません。試してみることはできますstraceが、より良いメカニズムがあるかどうか疑問に思っています

4

2 に答える 2

7

考えられる方法の1つは、を使用することgdbです。

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

この例のために、このPerlスクリプトを実行してみましょう。

$ 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: 15764
line 9
line 10
line 9
line 10
^C

それでは、gdbを起動しましょう。現在実行中のtest.plによって印刷されたpidを使用します。いくつかの初期情報(「...から記号を読み取る」)の後にプロンプ​​トが表示されます。

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

その間、gdbをperlインタープリターに接続しているため、perlは停止します。

$ ./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はsleep()の途中でたまたま停止しました。しかし、どれですか?

次に、現在実行中の(Perl)ソースファイルと行でperlの内部情報を探す場所を特定する必要があります。もともと私はmod_perlのdoumentationにいくつかの関連情報を見つけました。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->Tcurcop私が探していたものを。という名前で見つけましたmy_perl->Icurcop。現時点では、perlの内部に精通していないため、名前が変更された理由がわかりません。

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

于 2012-07-07T14:42:05.250 に答える
1

スクリプトを再起動できないと言っているのは知っていますが、一度再起動できた場合、ログに記録するのではなく、Signal::StackTrace などを使用してみてください。 USR2 を実行し、スタック トレース ダンプを取得します。

于 2012-04-29T12:02:11.933 に答える