5

pcntl_waitのPHPドキュメントによると、

待機関数は、子が終了するまで、または現在のプロセスを終了するかシグナル処理関数を呼び出すアクションを持つシグナルが配信されるまで、現在のプロセスの実行を一時停止します。

ただし、次のコードを実行し、シグナルハンドラーを使用してSIGTERMを親プロセスに送信すると、子が終了したkill -s SIGTERM [pid]にのみ呼び出されます(つまり、スリープが終了するのを待つ必要があります。SIGTERMによって中断されるべきではありませんか?pcntl_wait()

fork_test.php:

<?php
  declare(ticks = 1);

  function sig_handler($signo) {
    switch ($signo) {
      case SIGTERM:
        echo 'SIGTERM' . PHP_EOL;
        break;
      default:
    }
  }

  pcntl_signal(SIGTERM, 'sig_handler');

  $pid = pcntl_fork();

  if ($pid == -1) {
     die('could not fork');
  }
  else if ($pid) {
    echo 'parent' . PHP_EOL;

    pcntl_wait($status);
  }
  else {
    echo 'child' . PHP_EOL;
    sleep(30);
  }
?>

出力(SIGTERMは30秒待機した後にのみ表示されます):

$ php fork_test.php
child
parent
SIGTERM

PHPバージョン=>5.3.3

4

2 に答える 2

4

の呼び出しpcntl_signalは、呼び出しを再開する必要があることを指定します。ドキュメントを確認してください。デフォルトですrestart_syscallstrueしたがって、子が終了するまで、への呼び出しpcntl_signalは戻りません。

フラッシュする必要はありません。したがって、PHPはの出力をechoバッファーに保持できます。

したがって、表示されている動作は、まさに要求している動作です。システムコールが再開され、出力がバッファリングされます。

于 2012-04-24T01:03:36.720 に答える
0

pcntl_waitrestart_syscalls=falseOR子が死亡しない限り、信号によって通話を中断することはできません。

waitsyscallのドキュメントから(これは何pcntl_waitを呼び出すかです):

...子が状態を変更するか、シグナルハンドラが呼び出しを中断するまでブロックします(システムコールがsigaction(2)のSA_RESTARTフラグを使用して自動的に再開されないことを前提としています)。

最後の部分は非常に重要です。システムコールが自動的に再開されない場合にのみ、コールは中断されます(restart_syscalls=false)。

興味深いことに、プロセスがシグナルを受信したときに、すべてのsyscallが同じように動作するわけではありません。たとえば、sleepsyscallは秒数待機するか、信号を待機してから続行します。sleepパスしても中断された場所では再起動されませんrestart_syscalls=truesleepマニュアルから:

sleep()は、秒単位で指定されたリアルタイム秒数が経過するまで、または無視されないシグナルが到着するまで、呼び出し元のスレッドをスリープさせます。

TL; DR; を渡さない限り、pcntl_waitを中断することはできませんrestart_syscalls=false

于 2020-01-22T15:48:55.053 に答える