Perl eval 和 $SIG{__DIE__}

一般来说, Pel 中的 eval 可以捕获异常。 至少我是这样用的: 用来尝试运行一些操作,要是出错了也不会退出。 比如我经常用 Image::Info 来判断一个图像文件是否真的是图像,但是服务器上是否有 Image::Info是个问题。 简单概念代码如下:

code      eval("use Image::Info qw(image_info);");
      if ($@ eq "")
      {
            my $info = image_info("$tmpfilename");
            if ($info->{error} eq "Unrecognized file format"){
             $esB::base->error("该文件不是合法的图片文件。");
            }
      }

由于 eval 的存在, 如果系统没有 Image::Info ,那么简单的跳过判断,并不影响程序的继续执行。。

直到有一天, 我决定用 $SIG{__DIE__} 来自定义程序的的出错信息。 一样,概念代码如下

code $SIG{__DIE__} = \&esb_die;

 sub esb_die {
      my $error = shift;
      $error =~ s!$ENV{'DOCUMENT_ROOT'}!/{you_root_dir}/!i;
   my ($msg, $path) = split " at ",$error;
   print "Content-type: text/html\n\n";
   print qq~
    <html>
    <head><title>Easun CGI Error</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" >
    </head>
    <body >
    <font size='6' color='#333366'>Easun CGI Error</font>
    <hr size='1' color='#000000' noshade>
    <font size='3' color='#00000'>
    很抱歉,程式因为以下错误而异常退出:
    <br><br><b>$msg</b><br><br>错误大概发生在: <font color='#000099'>$path</font><br><br>
    <font size='3' color='#990000'><b>请注意,为了保证您的安全,您的程序的真实路径已经被程式自动过滤。</b></font>
    </font>
    </body></html> ~;
    exit();
}

该操作也达到预期目的。

但是,当这两者同时运行时,$SIG{__DIE__} 居然捕获到了 eval 内的 $@ 。当系统没有找到Image::Info 时候,程序不再默默跳过继续执行。而是直接跳出到自定义错误页面。
信息如下

很抱歉,程式因为以下错误而异常退出: Can't locate Image/Info.pm in @INC (you may need to install the Image::Info module) (@INC contains: ./config ./ShareLib ./ D:/usr/site/lib D:/usr/lib .) 错误大概发生在: (eval 10) line 1.

如何协调这两者,是个问题。。。

记录下来,作为备忘。