4

私は定期的にいくつかの作業を行い、それを繰り返す前にしばらくスリープするデーモンを書いています。ただし、スリープ中も外部からの影響 (つまり、終了要求) に応答する必要があります。

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() が干渉していますか?

また、タイムアウトとシグナル処理を同時に実装する他の手段はありますか?

4

1 に答える 1

4

それは完全に予想外というわけではありません。

シグナル ハンドラーへの配信を要求しましたが ( pcntl_signal(...))、ハンドラーを呼び出さずにシグナルを受け入れるよう要求しました ( pcntl_sigwaitinfo(...))。あなたのOSはこの場合に何が起こるかを決定し、あなたのOS(私のようなもの)はpcntl_sigwaitinfo()勝つことを選択します.

バックグラウンド

プロセスは、次の 2 つの異なる方法でシグナルを受け取る (「苦しむ」) ことができます。

  1. 非同期配信

    シグナルは、何らかの非同期アクションを引き起こします。通常は、プロセスを強制終了するか、ユーザー定義のハンドラーを呼び出します。pcntl_signalそのようなハンドラーを登録します。

    C プログラマーになじみのある基本的な呼び出しはsignalsigactionです。

  2. 同期受付

    特別なシステム関数は、シグナルが保留中であることに注意し、保留中のリストからそれを削除して、シグナルに関する情報をプロセスに返します。 pcntl_sigwaitinfoはそんな機能です。

    基礎となる呼び出しはsigwaitsigwaitinfoおよびsigtimedwaitです。

これら 2 つの方法、配信受諾異なるものであり、一緒に使用することは意図されていません。たとえば、AIX は単純に「[c]oncurrent use of sigaction and sigwaitを禁止しています。

(上記に関連するのは、シグナルを「ブロック」できるシグナルマスクの概念であり、シグナルが受け入れられるまで、または「ブロック解除」されて配信されるまで、効果的に保留状態を強制します。)

于 2012-10-11T03:08:05.380 に答える