Разветвление PHP и несколько дочерних сигналов

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

В основном существует единственный сценарий, который работает в цикле приблизительно в течение минуты, периодически опрашивая базу данных, чтобы видеть, существует ли задача, которая будет выполнена. Если существует один, это должно разветвить и выполнить задачу в отдельном процессе так, чтобы родитель не поддержался продолжительной задачей.

Так как возможно могло быть большим количеством задач, готовых быть выполненными, я хочу ограничить количество дочерних процессов, которые создаются. Поэтому я отслеживаю количество процессов путем постепенного увеличения переменной каждый раз, когда каждый создается (и затем приостановка, если существуют слишком многие), и затем постепенное уменьшение его в обработчике сигналов. Отчасти как это:

define(ticks = 1);

$openProcesses = 0; // how many we have open
$max = 3;           // the most we want open at a time

pcntl_signal(SIGCHLD, "childFinished");

while (!time_is_up()) {
    if (there_is_something_to_do()) {
        $pid = pcntl_fork();
        if (!$pid) {      // I am the child
            foo();        //   run the long-running task
            exit(0);      //   and exit
        } else {          // I am the parent
            ++$openProcesses;
            if ($openProcesses >= $max) {
                pcntl_wait($status);    // wait for any child to exit 
            }                           // before continuing
        }
    } else {
        sleep(3);
    }
}

function childFinished($signo) {
    global $openProcesses;
    --$openProcesses;
}

Это работает в значительной степени хорошо большую часть времени, за исключением того, когда два или больше процесса заканчиваются одновременно - функцию-обработчик сигнала только называют однажды, который выводит мой счетчик. Причина этого объяснена "Анонимным" в примечаниях к руководству PHP:

Несколько детей возвращают меньше, чем число детей, выходящих в данный момент, о котором сигнализирует SIGCHLD, нормальное поведение для Unix (POSIX) системы. SIGCHLD мог бы быть считан, поскольку "один или несколько детей изменились, состояние - идут, исследуют Ваших детей и получают их значения состояния".

Мой вопрос - это: Как я исследую детей и получаю их состояние? Там какой-либо надежный путь состоит в том, чтобы проверить, сколько дочерних процессов открыто в любой момент времени?

Использование PHP 5.2.9

8
задан nickf 16 February 2010 в 06:54
поделиться

1 ответ

Вы можете попросить детей отправить SIGUSR1 для родителя при запуске, затем SIGUSR2 перед выходом. Другая вещь, с которой вы имеете дело при использовании примитивных сигналов, - это объединение их ядром, чего не происходит с сигналами RT. Теоретически можно объединить ЛЮБОЙ не-rt сигнал.

Вы можете реализовать какую-то простую блокировку с помощью sqlite, при которой только один дочерний элемент одновременно может иметь говорящую палку. Просто убедитесь, что дети обычно обрабатывают фатальные сигналы, чтобы они остались живы, чтобы освободить замок.

0
ответ дан 6 December 2019 в 01:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: