私は定期的にいくつかの作業を行い、それを繰り返す前にしばらくスリープするデーモンを書いています。ただし、スリープ中も外部からの影響 (つまり、終了要求) に応答する必要があります。
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
同時に、このハンドラーを設定しないと、アンハンドラー シグナルが原因でスクリプトが停止します。
私は何かが欠けていますか?シグナル ハンドラ関数が呼び出されないのはなぜですか? pcntl_sigwaitinfo() が干渉していますか?
また、タイムアウトとシグナル処理を同時に実装する他の手段はありますか?