2010-01-27 5 views
0

이것은 Apache 2.2의 mod_perl2이며, win32의 ActiveState Perl 5.10입니다.

나는 $SIG{__DIE__}을 무시하고 데이터베이스 호출이 실패 할 때 내 재정을 호출해야합니다, 워드 프로세서에서 AFAICT DBI의 RaiseError 플래그를 켭니다. 한 가지 경우를 제외하고는 거의 항상있는 것으로 보이며 그 이유를 이해할 수 없습니다.

내 스크립트가 our $page 변수와있는 mod_perl2를을 가지고, 그래서 같은 재정에서이에서 얻을 수 있습니다 : 이것은 잘 작동

use Carp::Trace; 
my $full_trace = Carp::Trace::trace; 
$full_trace =~ m/^(ModPerl::ROOT::ModPerl::Registry::.*::)handler .*$/m; 
my $page; 
if (defined $1) 
{ 
    eval '$page = $' . $1 . 'page'; 
    if (defined $page) 
    { 
     $json = 1 if defined $$page{json_response}; 
     if (defined $$page{dbh}) 
     { 
      my $errno = $$page{dbh}->state; 
      if ($errno ~~ $$page{error_handling}{allowed}) 
      { 
       # allowed to let it go--no report, expected possible user error at some level that couldn't be caught sooner (usually db level) 
       my $errmsg = $$page{error_handling}{translation_map}{$errno}; 
       if (defined $errmsg) 
            { 
               ... 

. 이제 그 $page 내에서 DB에서 돌아올 때와 다른 뭔가를하고 싶다는 '허용 된'오류 값의 배열 참조가 있습니다. DB에서 이러한 오류 중 하나가 발생하면이를 JSON에서 사용자 친화적 인 메시지 $r->print으로 변환하고 실행을 중단합니다 (동작 A). 어떤 이유로, 대신 스크립트에 제어권을 반환합니다 (B 행동).

여기 내 스크립트의 주요 부분이다 : 나는 첫 번째 줄을 주석 경우

{ 
    $$page{error_handling}{allowed} = ['22007']; 
    $$page{json_response}{result} = $page->one_liner("select 'aa'::timestamp"); 
    $$page{json_response}{test} = $$page{error_handling}{state}; 
} 
    $page->make_json; # just JSONifies $$page{json_response} and prints it 

가, 내가 기대하는 것입니다 (행동 C), (예상치 못한 처리) 정상적인 오류가 나는 때문에 허용 된 오류 목록에 발생한 오류를 추가하지 않았습니다. 정말 이상한 점은 첫 번째 줄을 잘라 내 $SIG{__DIE__} 재정의에 붙여 넣으면 작동합니다. {test}이 할당되기 전에 JSON 응답이 무시되고 인쇄되고 실행이 중지됩니다 (동작 A). 낯선 사람은 여전히 ​​숫자 집합에 {allowed}을 설정할 수 있으며 특히 '22007'이 포함되어있는 한 B 행동을합니다. 그렇지 않으면 C 행동을합니다. 더 이상한 것은 실제로 채울 수 있습니다. 오버라이드가 더 이상 가능하지 않은 코드를 포함하고 있지 않더라도 아무 것도 무시하고 (경고, CORE::die 등의 호출 - 컴파일 할 때까지) 오버라이드하고 동작 B를 얻습니다! 또한 warnCORE::die에 대한 호출의 예상 된 결과를 얻지 못하고 로그에 침묵합니다. 따라서 수동으로 내 재정의를 통해 실행 경로를 추적 할 수도 없습니다.

모든 스크립트 저장 사이에 Apache2.2를 다시 시작했습니다. 나는 오버라이드를 스크립트 자체와 동일한 스크립트 파일로 옮겼다. 일반적으로 모듈 밖에서는 무시하고 오버라이드가 정상적인 곳의 전체 모듈 파일을 주석 처리하고 다시 시작했다. 내가 그 첫 번째 라인을 가지고, 또는 그것의 '22007'을 가지고가는 경우에

, 내가 할 수 warndie 그렇지 않으면 수동으로 내가 좋아하는 모든 디버깅, 그리고 모든 것이 예상대로 작동합니다. '22007'은 서버 리셋에도 불구하고 전혀 다른 결과를 출력하지 않는다는 점은 무엇입니까? '22007'에 대한 참조는 번역지도를 제외하고 전체 프로젝트의 어느 곳에서도 찾을 수 없으며 해당 파일에서 전체를 삭제하고 다시 시작할 수 있으며 결과도 다릅니다. 마치 이전에 내 오버라이드를 캐싱 한 것처럼 작동하며 결코 잊지 않습니다. 그것은 임의의 쿼리 문자열을 추가 할 수 있기 때문에 브라우저 캐시 문제가 아니며 결과도 다르지 않습니다.

이것은 내가 경험 해본 경험 중 가장 이상하고 가장 좌절 한 mod_perl2 경험이며 아이디어가 부족합니다. 아무도 어떤 힌트를 가지고 있습니까? 내가 생각할 수있는 유일한 문제는 캐싱 문제이지만, 서비스를 셀 수없이 다시 시작한 것입니다.

하루가 끝나면 서버 컴퓨터를 완전히 다시 시작하려고했지만 이후에는 아무 것도 변경되지 않았다고 생각했습니다.

$$page{error_handling}{state} = 'my face'; # $errno; 

그럼에도 불구하고, 이후에 '22007'로 {test} 있었다 출력, 내가 떠난 경우에만해야한다 무엇 : 난, 서버를 다시 시작하기 전에, {state}이 할당 된 전용 라인을 변경 = $errno. 그대로.

리버스 프록시가 캐싱을 수행하는 경우에도 요청이 다를 수 있으므로이 상황은 나에게 의미가 없습니다. 전체 서버를 다시 시작한 후에도 더 이상 코드에없는 값을 할당하는 방법, 즉 파일을 더 이상 존재하지 않는 경우 전체 다시 시작한 후에 이전 $SIG{__DIE__} 재정의를 어떻게 사용할 수 있습니까?

업데이트 : 또한 허용 된 오류를 '42601'로 변경하고 db 코드를 'select'으로 변경하여 오류 코드를 생성했지만 변환 맵에 추가하지 않았습니다. 그것은 여전히 ​​행동 ​​B를주고, {state}을 '42601'로 설정하여 '22007'과 관련이 없습니다. {allowed}에 입력 된 오류 코드는 오류가 실제로 발생하면 이전 버전의 재정의를 실행합니다. {allowed}에없는 오류가 발생하고 현재 버전이 실행됩니다. 그러나 현재 오류가 {allowed}에 있는지, 아니면 재정의에 도달하기 전에 어떤 의미인지 여부를 어떻게 알 수 있습니까? (오버라이드가 현재 오류 때문에 grepped 된 유일한 장소입니다.

답변

0

이것은 일시적인 임시 해결 방법이지만 미스테리를 해결하고 DB 호출이있는 곳이면 추가 라인을 추가하지 않아도됩니다. 허용 된 오류가 있습니다.

package MyModule::ErrorLogging; 
sub InsanityWorkaround # duplicates part of $SIG{__DIE__} override for allowed errors 
{ 
    my ($page) = @_; 
    my $r = $$page{r}; 
    my $errno = $$page{error_handling}{state}; 
    if ($errno ~~ $$page{error_handling}{allowed}) 
    { 
     # allowed to let it go--no report, expected possible user error at some level that couldn't be caught sooner (usually db level) 
     my $errmsg = $$page{error_handling}{translation_map}{$errno}; 
     if (defined $errmsg) 
     { 
      use JSON::XS qw(encode_json); 
      $$page{json_response} = 
      { 
       error => $errmsg, 
      }; 
      my $response = encode_json($$page{json_response}); 
      $r->content_type("application/json"); 
      $r->print($response); 
      exit(0); 
     } 
     else 
     { 
      return 0; # get back to script where {state} can be checked and output can be customized even further 
     } 
    } 
    return; 
} 

그런 다음 내 스크립트가됩니다 :

{ 
    $$page{error_handling}{allowed} = ['22007']; # don't be bothered by invalid timestamp error 
    $$page{json_response}{result} = $page->one_liner("select 'aa'::timestamp"); 
    MyModule::ErrorLogging::InsanityWorkaround($page); 
} 

이 행동 A.

을주고있다