Article

Демон 2: Простенькая обработка сигналов

Ок, теперь, после http://jasper-vexxel.890m.com/web/article/show/9 у меня есть демон, который что-то могёт, но пока что мне этого мало.

Теперь стоит задача научить демона обрабатывать системные сигналы, для более качественного взаимодействия с пользователями( например,наш скрипт делает excel отчет, и мы прерываем его на половине процесса ( хз зачем, но допустим что реально мы), то очень не хотелось бы просто так потерять 50% от прогресса, который скрипт недовыполнил, да и как то чтоли в логи записать, что у нас есть в итоге):

Мат.часть:

Основные новые ф-и, которые мне пригодились:

  • declare(ticks=1) ==> установка директив для блока кода, который находится ниже
  • posix_setsid() ==> назначить PID дочернему процессу
  • posix_getsid(0) ==> получить PID дочернего процесса
  • pcntl_signal($sigName,$sigHandlerName) ==> назначть обработчик для POSIX сигнала

Суть дела:

Есть процесс, а есть сигнал.
Процесс ==> наш демон
Сигнал ==> вызывается на событие, прерывает работу процесса, и завершается после выполнения заданного(если есть) обработчика
Наша задача - научится обрабатывать сигналы, которые могут прийти с консоли

Доп.теория:

Сигнал в консоле назначается как: kill -SIGNALNAME PID
Пример 1: kill -SIGINT 5487
Пример 2: kill 5487
****Если мы сами явно не указываем сигнал для процесса, default сигнал - SIGTERM

В итоге, у меня в файле отрисуется код, который наявно покажет PID, forkerPID

<?php
/**
 * Простой демон 2, теперь он умеет обрабатывать сигналы POSIX
 */
# declare ==> установка директив для исполнения блока кода, расположенного ниже declare
declare(ticks=1);
$status=true;
function sigHandler($signal)
{
    global $status;
    switch ($signal)
    {
        case SIGTERM:
//Пример 1: я просто обрабатывал сигнал
//            echo "Делаем что-то по приходу сигнала об окончании процесса";
//            sleep(15);
//            # спокойно ложим демона
//            $status=false;
//            break;
            # а теперь, я попробую положить процесс внутри процесса (сам корректно обработать его завершение
            # + оповестить об этом пользователя ) == неудалось
            $status=false;
            echo "Процесс завершился корректно, данный демон отключен";
            break;
        case SIGUSR1:
            echo "Была вызвана функция 1";
            break;
        case SIGUSR2:
            echo "Была вызвана функция 2";
            break;
        default:
            echo "Была вызвана ф-я, которая нас, мягко говоря не ебёт";
            break;
    }
}
//---------------------------------------------------------------------------------------------------------------
// Блок обработки входящих сигналов
pcntl_signal(SIGTERM,'sigHandler');
pcntl_signal(SIGUSR1,'sigHandler');
pcntl_signal(SIGUSR2,'sigHandler');
$pid=pcntl_fork();
if($pid==-1)
{
    exit('Error. Process'.$pid.' wasn`t forked!');
}
elseif($pid)
{
    exit('Kill parent process');
}
else {
    posix_setsid();
    $posix_id=posix_getsid(0);
    $fileName='/var/www/simple-project.loc/files/test3.txt';
    $counter=0;
    while($status)
    {
        $a=file_get_contents($fileName);
        # тут для наглядности представленные данные с таких ф-й
        # pcntl_fork        ==> PID
        # posix_getsid      ==> posix_getsid
        $b='PID = '.$pid. ', posix_getsid ==> '.$posix_id.' counter ==> '.$counter."\n";
        file_put_contents($fileName,$a.$b);
        sleep(5);
        $counter++;
        if($counter>11)$status=false;
        # пример с собственным завершением внутри процеса
    }
//--------------------------------------------------------------------------------------------------
/**
 * Итого, данный демон уже может обрабатывать команды, но, пока что не может завершится, известив
 * корректно об этом пользователя
 */
}

Third-party source 2
Dropdown
test 123