доброго времени суток. Пишу небольшой демон на php.
Возникла проблема в том что не могу понять как завершать дочерние процесы.
Код демона нарыл на
хабаре
То что сейчас у меня:
PHP код:
<?php
pcntl_signal_dispatch();
//declare(ticks=1);
class DaemonClass {
// Максимальное количество дочерних процессов
public $maxProcesses = 5;
// Когда установится в TRUE, демон завершит работу
protected $stop_server = FALSE;
// Здесь будем хранить запущенные дочерние процессы
protected $currentJobs = array();
protected $socket;
protected $conf = array();
public function __construct() {
echo "Сonstructed daemon controller".PHP_EOL;
// Ждем сигналы SIGTERM и SIGCHLD
pcntl_signal(SIGTERM, array($this, "childSignalHandler"));
pcntl_signal(SIGCHLD, array($this, "childSignalHandler"));
}
public function Create(){
$this->conf = Config::Ini('config.ini', 'config');
// Создание сокета TCP:
// возвращает дескриптор сокета
if(($this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0)
{
error_log('Невозможно создать сокет: '.socket_strerror(socket_last_error())."\n");
}else{
// Биндим сокет на определённый адрес и порт:
if(($error = socket_bind($this->socket, $this->conf->host, $this->conf->port)) < 0)
{
error_log('Невозможно привязать сокет: '.socket_strerror(socket_last_error())."\n");
}else{
//Прослушиваем сокет:
if(($error = socket_listen($this->socket, 5)) < 0)
{
error_log('Невозможно прослушать сокет: '.socket_strerror(socket_last_error())."\n");
}else{
$this->run();
}
}
}
}
protected function run(){
echo "Running daemon controller".PHP_EOL;
// Пока $stop_server не установится в TRUE, гоняем бесконечный цикл
while (!$this->stop_server) {
// Если уже запущено максимальное количество дочерних процессов, ждем их завершения
while(count($this->currentJobs) >= $this->maxProcesses) {
echo "Maximum children allowed, waiting...".PHP_EOL;
sleep(1);
}
$this->launchJob();
}
// Закрываем сокет
socket_close($this->socket);
}
protected function launchJob() {
// Создаем дочерний процесс
// весь код после pcntl_fork() будет выполняться
// двумя процессами: родительским и дочерним
$pid = pcntl_fork();
if($pid == -1) {
// Не удалось создать дочерний процесс
error_log('Could not launch new job, exiting');
return FALSE;
}elseif($pid){
// Этот код выполнится родительским процессом
$this->currentJobs[$pid] = TRUE;
}else{
// А этот код выполнится дочерним процессом
echo "Процесс с ID ".getmypid().PHP_EOL;
// ожидаем соединение
if(($accept = socket_accept($this->socket)) < 0)
{
error_log('Ошибка при чтении');
// закрываем соединение
socket_close($accept);
unset($this->currentJobs[$pid]);
exit();
}else{
print(date("Y-m-d H:i:s", time())." STATUS: client connected.\n");
// Считываем заданное количество байт из указанного сокета
if(FALSE === ($line = @socket_read($accept, 2048)))
{
error_log('Невозможно прослушать сокет: '.socket_strerror(socket_last_error())."\n");
socket_close($accept);
unset($this->currentJobs[$pid]);
exit();
}else{
$query = trim($line);
file_put_contents(DOCUMENT_ROOT."/query.log", $query."\n", FILE_APPEND);
unset($this->currentJobs[$pid]);
exit();
}
}
}
return TRUE;
}
public function childSignalHandler($signo, $pid = null, $status = null) {
switch($signo) {
case SIGTERM:
// При получении сигнала завершения работы устанавливаем флаг
$this->stop_server = true;
break;
case SIGCHLD:
// При получении сигнала от дочернего процесса
if (!$pid) {
$pid = pcntl_waitpid(-1, $status, WNOHANG);
}
// Пока есть завершенные дочерние процессы
while ($pid > 0) {
if ($pid && isset($this->currentJobs[$pid])) {
// Удаляем дочерние процессы из списка
unset($this->currentJobs[$pid]);
}
$pid = pcntl_waitpid(-1, $status, WNOHANG);
}
break;
default:
// все остальные сигналы
}
}
}
проблема возникает в самом
launchJob.
Как видите тут:
PHP код:
unset($this->currentJobs[$pid]);
exit();
я пытался убрать запись о процессе