0

proc_open を使用してサードパーティの perl スクリプトを開くカスタム php スクリプトがあります。pcntl_signal ハンドルをいくつか入れようとしていたので、割り込み時に適切にクリーンアップできました。

シグナル ハンドラーを、ループなどで回転するだけの、より限定されたテスト ベッドで動作させることができます。

ただし、proc_open を使用して子スクリプトをループしている場合、CTRL+C はその場で完全に停止しているように見えます。明確にするために、親プロセスと子プロセスの両方を完全に即座に停止することを意味します。ctrl+c がサード パーティの子プロセスによってキャッチされているかのようではなく、戻ってスクリプトが続行されます

私はPHPのドキュメントを読んだことがありますが、信号処理はsleep()のようなものではうまく機能しないことが知られており、POSIX proc_open関数と同様のものである可能性があると考えました。SO を見てみると、状況に応じて、シグナル処理を子プロセスに移動するか、restart_syscalls パラメータを proc_open に切り替えるという解決策を含むいくつかの同様の投稿があるようです。

restart_syscalls パラメータを false に切り替えてみましたが、うまくいきませんでした。

残念ながら、子プロセスはサード パーティのスクリプトなので、実際のコードには詳しくありません。信号を元に戻すためにあれこれいじる前に (それが可能である場合、または行うべきことでさえある場合)、自分のコードだけを維持できるように、自分のセットアップに何か欠けているものがないか疑問に思っていました。

私が持っているものは次のように見えます

<?php

declare(ticks=1);

class signalHandler{

    public static function handle($signal){
        throw new KillException("Received Kill signal $signal", $signal);
    }

}
pcntl_signal(SIGINT,array('signalHandler','handle'));

その後、実際の子プロセスを呼び出します。

$childCmd = "thirdPartyScript.pl";

// Set up how we'll interact with the IO file handlers of the process
$descriptors = Array(
    0 => Array('file', '/dev/null', 'r'), // Process will read from /dev/null
    1 => Array('pipe', 'w'), // Process will write to STDOUT pipe
    2 => Array('pipe', 'w')  // Process will write to STDERR pipe
);

// Start the process
$childProc = proc_open($childCmd, $descriptors, $pipes);

// Check the status of the backup every second...
$streamContents = '';

stream_set_blocking($pipes[2], 0);
do {
    $streamContents .= stream_get_contents($pipes[2]);

    if( ! ( $childStatus = proc_get_status($childProc) ) ) {
        throw new Exception("Error: Unable to retrieve status on child process.");
    }


} while ($childStatus['running']);
4

1 に答える 1

0

お子様が亡くなったときに通知を受け取りたい場合は、SIGCHLDも聞く必要があります。たとえばsleep(1)をポーリングサイクル内に安全に配置して、忙しい作業を減らすこともできると思います。

于 2013-02-14T02:50:09.160 に答える