2012-03-22 2 views
2

Inotify2를 사용하여 들어오는 파일의 디렉토리를 감시하는 Perl로 작성된 데몬 프로세스가 있습니다. 각 파일이 도착하면 데몬은 하위 프로세스를 포크합니다. 자, 내가 내 로그 파일에서이 오류를 얻었 기 때문에 너무 많은 파일이 동시에 (따라서 너무 많은 포크)에 도착하는 것 같다 포크의 결과입니다perl의 파일 시스템 이벤트에서 하위 프로세스 포킹

Cannot allocate memory at notifyd.pl line ... 

을(). 내가 프로세스를 분기하지 않음으로써 이벤트를 놓칠 여유가 없다

sub watcher { 
     my $e = shift; 
     my $pid = fork(); 
     if(!defined $pid) { 
      print "[ERROR]", $!; 
     } 
     elsif($pid == 0) { 
      my @args = ($e->fullname, $e->mask); 
      exec($childprocess, @args) or die($!); 
     } 
} 

: 포크와 다음 execv와 일을

my $inotify = new Linux::Inotify2() or die($!); 

    foreach my $k (@PATHS) { 
     $inotify->watch($k, 
IN_MOVE_SELF|IN_DELETE_SELF|IN_CLOSE_WRITE, \&watcher) or die($!); 
    } 

    $inotify->blocking(1) or die($!); 

    for(;;) { 
     $inotify->poll() or die($!); 
    } 

감시자 기능 :

는 기본적으로 나는 다음과 같은 코드가 있습니다.

누구나 내가 이것을 개선하고 포크가 실패하지 않도록하는 방법에 대한 제안 사항이 있습니까?


편집 : 그것은 데몬이 SIGCHLD에 응답하지 것이기 때문에 그들이 종료되면 자식 프로세스가 좀비가되는 것처럼 보인다. 그래서 많은 zombie 자식 프로세스가 fork()가 실패한 이유가 될 수 있습니다. 데몬은 이제 분기하기 전에 $SIG{CHLD} = 'IGNORE';을 수행합니다.

+1

파일을 많이 변경 한 경우 리소스를 소모하기가 쉽고 사용 사례에 따라 도스 공격의 벡터입니다. cpan에서 이벤트 루프 중 하나를 사용하여 해당 이벤트를 처리해야합니다. AnyEvent를 살펴 보는 것이 좋은 출발점이 될 수 있습니다. –

+0

fork()가 실패 했습니까? (부분적으로) 존재하는 에러 메세지는'die' 또는'warn'에서 나온 것처럼 보이지만 fork가 실패한 경우 (즉, $ pid가 정의되지 않은 경우) 표시 한 코드는 출력을 생성하지 않습니다. – pilcrow

+0

예, 메시지의이 부분에서 온 메시지는 if (! $ pid) {print "[ERROR]", $ !; } –

답변

2

간접 참조의 다른 계층을 추가하여 문제를 해결하십시오.

이벤트를 받으면 파일 이름을 job queue에 넣으십시오. 리소스가 합리적으로 여유가 없을 때 큐는 파일을 처리하는 새로운 작업을 시작합니다. 이 계획은 이벤트가 결국에는 즉시 실행되도록 보장합니다. 모든 이벤트가 즉시 처리되는 것은 아닙니다.

+0

감사합니다. 구현할 수있는 방법을 조사해야합니다. 문제는 큐를 처리하기위한 또 다른 프로세스를 갖고 싶지 않을 것입니다. –

2

사용 Forks::Super

이 설정 같은보다 강력한 백그라운드 프로세스 매니저는, 예를 들어, 한 번에 실행 최대 10 포크를해야합니다. 10 개의 포크가 모두 사용 중일 때 새로운 요청이 대기열에 배치됩니다. 큐에있는 작업은 다른 백그라운드 프로세스가 완료되고 리소스를 사용할 수있게되면서 실행됩니다.

use Forks::Super MAX_PROC => 10, ON_BUSY => 'queue'; 

... 

sub watcher { 
    my $e = shift; 
    fork { 
     sub => sub { 
      my @args = ($e->fullname, $e->mask); 
      exec($childprocess, @args) or die($!); 
     } 
    }; 
} 
+0

감사합니다. 모듈을 설치하지 못할 수도 있다는 것을 제외하고는보기에 좋았 기 때문에 비슷한 것을 구현해야 할 것입니다. –