Я пытаюсь написать скрипт, который создает несколько разветвленных дочерних процессов, используя 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