使用mod_perl捕获异常上的堆栈跟踪

时间:2012-10-26 22:19:34

标签: perl apache cgi mod-perl

我正在将一些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进行评估,但我从上面的例行程序中进行了eval检查,但我仍然没有被调用。

有什么方法可以在mod_perl下得到我想要的东西吗?我发现堆栈跟踪的这些自动记录非常有用,如果我不得不放弃它们会错过它们。到目前为止,我已经找不到如何获得它。

1 个答案:

答案 0 :(得分:1)

我不知道答案,但可以想到一些可能性和方法来检查。

  • log4perl出了点问题。

FATAL的调用是否仍在__DIE__处理程序之外?

  • 根本没有记录错误。

删除模具处理程序,是否记录异常?

  • 正在替换您的$SIG{__DIE__}处理程序。

由于您在BEGIN时间进行设置,因此Apache2 :: Registry或其他程序中的某些内容可能会替换它。我会在抛出错误之前通过验证$SIG{__DIE__}中的内容来找出答案。或许可以使用Data::Dump::Streamer将其转储出来,它可以处理代码引用,你或许可以弄清楚是什么设置它。

注册模具处理程序的更安全,更礼貌的方式是......

local $SIG{__DIE__} = ...;

...the rest of your program...

这将在每个请求上重新注册您的处理程序,而不是超出其范围之外的全局处理程序。

希望有助于弄清楚发生了什么。