Как да изчакате чакането без да убиете детето?

Наясно съм с многото въпроси относно waitpid и timeouts, но всички те покриват това, като убиват детето от манипулатора на аларми.

Това не е това, което искам, искам да продължа процеса да работи, но да го изпратя от waitpid.

Основният проблем, който се опитвам да разреша, е процес на демон с основен цикъл, който обработва опашка. Задачите се обработват една по една.

Ако дадена задача увисне, целият основен цикъл увисва. Заобикалянето на тези fork() и waitpid изглеждаше очевиден избор. И все пак, ако задачата виси, цикълът виси.

Мога да се сетя за заобиколни решения, при които изобщо не използвам waitpid, но ще трябва да проследявам изпълняваните процеси по друг начин, тъй като все още искам да обработвам една задача наведнъж успоредно с евентуално висящи задачи.

Бих могъл дори да убия задачата, но бих искал да я пусна, за да проверя какво точно се обърка. Възможен е също манипулатор за унищожаване, който изхвърля информация за отстраняване на грешки.

Както и да е, най-удобният начин за решаване на този проблем е изчакване за чакане, ако е възможно.

Редактиране:

Ето как използвах fork() и waitpid и може да е по-ясно какво се има предвид под дете.

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";
}

person matthias krull    schedule 30.08.2011    source източник


Отговори (3)


Ако дадена задача увисне, целият основен цикъл увисва. Заобикалянето на този fork() и waitpid изглеждаше очевиден избор. И все пак, ако задачата виси, цикълът виси.

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

person Blagovest Buyukliev    schedule 30.08.2011

вместо периодично да проверявате всички деца, може да искате да настроите манипулатор на сигнали, който да обработва SIGCHLD... от perlipc:

 use POSIX ":sys_wait_h";
    $SIG{CHLD} = sub {
        while ((my $child = waitpid(-1, WNOHANG)) > 0) {
            $Kid_Status{$child} = $?;
        }
    };
    # do something that forks...
person KURT W ANDREWS    schedule 16.10.2013

Активирането и обработката на SIGCHLD също е възможност; той ще ви уведомява за промени в състоянието на дъщерния процес без запитване -- вижте sigprocmask(2) и signal(3) в страниците с ръководство.

person user2012529    schedule 25.01.2013