Я пишу демон, который периодически выполняет какую-то работу и некоторое время спит, прежде чем повторить ее снова. Но он все еще должен реагировать на внешние воздействия (например, запрос на завершение) во время сна.
Мне удалось реализовать тайм-аут сна с помощью сигнала ALRM и завершение с помощью сигнала TERM (пример):
// ...
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;
}
}
// ...
Но, ради бога, я не могу понять, почему сигхандлер никогда не вызывается. Я получаю следующий вывод:
$ php sigsample.php
Doing some work.
ALRM SIGWI
Doing some work.
ALRM SIGWI
Doing some work.
TERM SIGWI
И в то же время, если я не устанавливаю этот обработчик, скрипт умирает из-за сигнала unhandler.
Я что-то упустил? Почему моя функция обработчика сигналов никогда не вызывается? Мешает ли pcntl_sigwaitinfo()?
И есть ли какие-либо другие средства для одновременной реализации тайм-аута и обработки сигнала?