Как тайм-аут ожидания, не убивая ребенка? - PullRequest
4 голосов
/ 30 августа 2011

Мне известно о многих вопросах, касающихся waitpid и тайм-аутов, но все они покрывают это, убивая ребенка из обработчика тревоги.

Это не то, что я хочу, я хочу, чтобы процесс продолжался, ноотправить его из waitpid.

Основная проблема, которую я пытаюсь решить, - это процесс демона с основным циклом, который обрабатывает очередь.Задачи обрабатываются по одной за раз.

Если задача зависает, весь основной цикл зависает.Обойти это fork() и waitpid казалось очевидным выбором.Тем не менее, если задача зависает, цикл зависает.

Я могу придумать обходные пути, когда я вообще не использую waitpid, но мне придется отслеживать запущенные процессы другим способом, так как я все еще хочу обрабатывать одну задачу за раз впараллельно с возможным зависанием задач.

Я мог бы даже убить задачу, но мне бы хотелось, чтобы она работала, чтобы проверить, что именно происходит не так.Также возможен обработчик уничтожения, который выводит некоторую отладочную информацию.

В любом случае, наиболее удобный способ решения этой проблемы - это тайм-аут ожидания, если это возможно.

Редактировать:

ЭтоВот как я использовал fork () и waitpid, и это может быть более понятно, что подразумевается под child.

my $pid = fork();

if ($pid == 0){
    # i am the child and i dont want to die
}
elsif ($pid > 0) {
    waitpid $pid, 0;
    # i am the parent and i dont want to wait longer than $timeout
    # for the child to exit
}
else {
    die "Could not fork()";
}

Редактировать:

Использование waitpid WNOHANG делает то, что я хочу.Является ли это использование хорошей практикой или вы сделали бы это по-другому?

use strict;
use warnings;
use 5.012;
use POSIX ':sys_wait_h';

my $pid = fork();

if ($pid == 0){
    say "child will sleep";
    sleep 20;
    say "child slept";
}
else {
    my $time = 10;
    my $status;
    do {
        sleep 1;
        $status = waitpid -1, WNOHANG;
        $time--;
    } while ($time && not $status );

    say "bye";
}

Ответы [ 3 ]

7 голосов
/ 30 августа 2011

Если задача зависает, весь основной цикл зависает. Чтобы обойти эту вилку () и waitpid казался очевидным выбором. Еще если задача зависает цикл висит.

Используйте waitpid с опцией WNOHANG. Таким образом, он не будет приостанавливать родительский процесс и немедленно вернет 0, когда ребенок еще не вышел. В вашем основном цикле вам придется периодически опрашивать всех детей (задачи).

3 голосов
/ 17 октября 2013

вместо периодического опроса всех дочерних элементов, вы можете настроить обработчик сигнала для обработки SIGCHLD ... из perlipc:

 use POSIX ":sys_wait_h";
    $SIG{CHLD} = sub {
        while ((my $child = waitpid(-1, WNOHANG)) > 0) {
            $Kid_Status{$child} = $?;
        }
    };
    # do something that forks...
1 голос
/ 26 января 2013

Включение и обработка SIGCHLD также возможно; он будет уведомлять вас об изменениях состояния дочернего процесса без опроса - см. sigprocmask (2) и signal (3) на страницах справочника.

...