pcntl sigwaitinfo и обработчики сигналов


Я пишу демона, который периодически выполняет некоторую работу и некоторое время спит, прежде чем повторить ее снова. Но он все равно должен реагировать на внешние воздействия (т.Е. запрос на завершение) во время сна.

Мне удалось реализовать тайм-аут ожидания с сигналом ALRM и завершение с сигналом СРОКА (образец):

// ...

declare(ticks = 1);

function do_work()
{
    echo "Doing some work.\n";
}

$term = FALSE;

$sighandler = function ($signal) use (&$term)
{
    if ($signal === SIGTERM)
    {
        pcntl_alarm(0);

        $term = TRUE;

        echo "TERM HANDLER\n";
    } else {
        echo "ALRM HANDLER\n";
    }
};

pcntl_signal(SIGALRM, $sighandler);
pcntl_signal(SIGTERM, $sighandler);

while (!$term)
{
    do_work();

    // Kick myself after 2 seconds
    pcntl_alarm(2);

    // Wait for alarm or termination
    $signal = pcntl_sigwaitinfo(array(SIGTERM, SIGALRM), $info);

    pcntl_signal_dispatch();

    switch ($signal)
    {
        case SIGALRM: echo "ALRM SIGWI\n"; break;
        case SIGTERM: echo "TERM SIGWI\n"; $term = TRUE; break;
    }
}

// ...

Но, ради Бога, я не могу понять, почему никогда не вызывается sighandler. Я получаю следующий результат:

$ php sigsample.php
Doing some work.
ALRM SIGWI
Doing some work.
ALRM SIGWI
Doing some work.
TERM SIGWI

И в то же время, если я не установлю это обработчик сценарий умирает из-за сигнала необработчика.

Я что-то упускаю? Почему моя функция обработчика сигналов никогда не вызывается? Мешает ли pcntl_sigwaitinfo()?

И существуют ли какие-либо другие средства для одновременной реализации тайм-аута и обработки сигналов?

Author: pilcrow, 2012-10-10

1 answers

Это не совсем неожиданно.

Вы запросили доставку обработчику сигнала (pcntl_signal(...)), но затем также попросили принять сигнал без вызова каких-либо обработчиков (pcntl_sigwaitinfo(...)). Ваша ОС решает, что произойдет в этом случае, и ваша ОС (как и моя) решает позволить pcntl_sigwaitinfo() победить.

Предыстория

Процесс может получать ("страдать?") сигнал двумя различными способами:

  1. асинхронная доставка

    Сигнал индуцирует некоторое асинхронное действие, обычно завершающее процесс или вызывающее пользовательский обработчик. pcntl_signal регистрирует именно такой обработчик.

    Базовые вызовы, знакомые программистам на языке Си, следующие signal и sigaction.

  2. синхронное принятие

    Специальные системные функции отмечают, что сигнал находится в ожидании, и удаляют его из списка ожидающих, возвращая информацию о сигнале процессу. pcntl_sigwaitinfo является ли такое функция.

    Основными вызовами являются sigwait, sigwaitinfo и sigtimedwait.

Эти два способа доставки и принятия являются различными и не предназначены для совместного использования . AIX, например, просто запрещает "[c] текущее использование sigaction и sigwait".

(С вышесказанным связана концепция маски сигнала, которая может "блокировать" сигналы, эффективно заставляя их оставаться в ожидании до тех пор, пока они не будут приняты или "разблокированы" и доставлены.)

 3
Author: pilcrow, 2012-10-11 03:08:05