1

一部の cgi スクリプトを mod_perl に変換しています。cgi では、sig DIE を使用して、キャプチャされていない例外が発生するたびにスタック トレースをキャプチャし、それらをログに記録しました。これはうまく機能しました。スクリプトで何かが停止するたびに、アプリケーション ログに適切なスタック トレースが記録されます。コードは次のとおりです。

BEGIN {
  $SIG{__DIE__} = \&sigDie;
}

sub sigDie {
  return 1 if $^S; # we are in an eval block

  my ($error) = @_;
  cluck("Caught fatal error: $error"); # put a stack trace in the logs via warn
  local $Log::Log4perl::caller_depth = $Log::Log4perl::caller_depth + 1;
  FATAL @_; # call log4perl's fatal

  return 1;
}

ただし、Apache2::Registry の下では、私のコードは呼び出されなくなりました。コードが終了すると、ログ記録が停止するだけです。これは、コードが mod_perl によって評価されているためだと思いましたが、上記のルーチンから評価チェックを外しましたが、まだ呼び出されていません。

mod_perl で必要なものを取得する方法はありますか? これらのスタック トレースの自動ログ記録が非常に便利であることがわかりました。これまでのところ、私はそれを取得する方法について空っぽになりました。

4

1 に答える 1

1

答えはわかりませんが、いくつかの可能性と確認方法を考えることができます。

  • log4perl に問題があります。

への呼び出しはハンドラーFATALの外でも機能しますか?__DIE__

  • エラーはまったく記録されていません。

ダイ ハンドラーを削除します。例外はログに記録されますか?

  • 何かが$SIG{__DIE__}ハンドラーを置き換えています。

あなたはそれを設定しているのでBEGIN、Apache2::Registry の何か、または別のプログラムがそれを置き換えている可能性があります。$SIG{__DIE__}エラーをスローする直前に何が入っているかを確認することでわかります。おそらく、コード参照を処理できるData::Dump::Streamerを使用してダンプすると、何が設定されているかを把握できる場合があります。

ダイハンドラーを登録するより安全で礼儀正しい方法は...

local $SIG{__DIE__} = ...;

...the rest of your program...

これにより、リクエストごとにハンドラーが再登録され、スコープ外のグローバルハンドラーが吹き飛ばされなくなります。

何が起こっているのかを理解するのに役立つことを願っています。

于 2012-10-26T23:43:59.157 に答える