perl, без дочернего процесса с открытым

Привет, у меня есть эта проблема, когда скрипт Perl выдает «Нет дочерних процессов, найденных в» ...

Мой скрипт вызывает несколько разных типов форков, поэтому я попытался реализовать метод реализации perldoc waitpid(), чтобы иметь возможность использовать хэндл как fork, так и exec, и system, и qw.

 $SIG{CHLD} = sub {
    # don't change $! and $? outside handler
    local ($!, $?);
    my $pid = waitpid(-1, WNOHANG) > 0;
    return if $pid == -1;
    return unless defined $children{$pid};
    delete $children{$pid};
};

    my $pid = fork();
    die "cannot fork" unless defined $pid;
    if ($pid == 0) {
        # ...
        exit 0;
    } else {
        $children{$pid}=1;
        # ...
        exec($command);
   }

С этой частью выполнения кода проблем нет, однако при попытке закрыть CLOSE дескриптора файла возникает сообщение «Не найден дочерний процессор». Может кто-нибудь объяснить мне, как это происходит, так как я действительно хочу глубже понять эту проблему. Должен ли я в конечном итоге пожинать дочерний процесс, разветвленный вызовом OPEN, так что закрытие не знает, как обращаться с дескриптором файла? или, может быть, я 100% off. Любые решения будут оценены

open(RESULTS, "-|", "find $dir\/ -maxdepth 1 -name RESULTS -print0 | xargs -0 cat ") or die $!;
while(<RESULTS>){
if($_ =~ /match/){
    print $_;
 }
  }
 close RESULTS;

person user1539348    schedule 03.10.2012    source источник


Ответы (1)


close на ручке*, открытой таким образом, вызывает waitpid, чтобы пожинать ребенка, созданного open. Однако ваш обработчик сигналов успел получить дочерний элемент раньше, чем close, поэтому close не смог найти дочерний элемент, поэтому close вернул ошибку.

Вы можете исправить это, изменив обработчик сигнала, чтобы он собирал только дочерние элементы, созданные вами с помощью fork (ниже), или вы можете игнорировать эту ошибку из close.

$SIG{CHLD} = sub {
   local ($!, $?, $^E);
   for my $pid (keys(%children)) {
      if (waitpid($pid, WNOHANG) > 0) {
         delete $children{$pid};
      }
   }
};

* Правильным термином является "дескриптор файла". Он назван так, потому что позволяет вам удерживать файл. Это не обработчик, поскольку он не выполняет никаких действий.

person ikegami    schedule 03.10.2012
comment
Что я должен сделать, чтобы изменить обработчик сигналов, чтобы получать только сигналы, сделанные вилкой? Вы имеете в виду что-то вроде этого?, размещение: return if ( grep{!$children{$_}}$pid); перед моим $pid = waitpid(-1, WNOHANG) › 0; - person user1539348; 04.10.2012
comment
Спасибо за ваш замечательный ответ. Последний вопрос. Какова цель создания локального $^E? - person user1539348; 04.10.2012