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.

如何協調這兩者,是個問題。。。

記錄下來,作為備忘。