More Related Content
Similar to signal の話 或いは Zend Signals とは何か
Similar to signal の話 或いは Zend Signals とは何か (20)
signal の話 或いは Zend Signals とは何か
- 3. signal とは
• UNIX系OS に古くからあるプロセス間通信の
一つ
• プロセスがシグナル(実態は整数) を受信す
ると、あらかじめ設定した処理(シグナルハ
ンドラ)が実行される(乱暴に言えば割り込
みが発生する)
• シグナルハンドラが設定されてないシグナル
は、無視されるかあるいは既定の動きをする
(その多くはプログラムの終了)
- 10. tick による dispatch
• declare(ticks = N); // (N >= 1)
– N個の tick 可能命令ごとに ZEND_TICKS opcode
が発行される
– 詳しくは以前書いた記事を参照
http://d.hatena.ne.jp/do_aki/20151204/14491
97226
• ticks=1 ならば、だいたい php スクリプト1行
ごとに発行されてる
– 1行ごとに pcntl_signal_dispatch が呼ばれるイ
メージ
• ファイル単位で、コンパイル時に影響
– ticks 指定忘れるとシグナルコールバックされない
- 11. vm_interrupt による dispatch
• pcntl_async_signals(true); // 7.1~
– declare(ticks=1) が不要になる
– pcntl_signal_handler が
EG(vm_interrupt) = 1 するようになる
• EG(vm_interrupt) が 1 の場合、 PHP VM は、
zend_interrupt_function (関数ポインタ) を呼ぶ
– Opcode ひとつ処理するたびにチェックしている
– pcntl の MINIT で
zend_interrupt_function = pcntl_interrupt_function
してて、このなかで pcntl_signal_dispatch を呼ぶ
– ZEND_TICKS Opcode で毎回呼ばれるよりも低コスト
– (async_signals しなくても pcntl 以外が vm_interrupt
をセットすれば dispatch される気がする)
- 13. EG(vm_interrupt)
• 元は Safe timeout handling により導入
された仕組み
• EG(vm_interrupt) かつ EG(timed_out)
ならば (zend_interrupt_function ではなく)
zend_timeout(0) を呼ぶ(おそらくこちらが本命)
• EG(timed_out) は php スクリプトの実行
時間が max_execution_time を超えたとき
に設定される
- 14. max_execution_time の実装
• setitimer (ITIMER_PROF)を利用 (!WIN32)
– プログラムの実行時間が指定時間経過すると
SIGPROF が飛ぶ
– php に kill –PROF すると終了する
• zend engine でシグナルハンドラ を設定し
てる
– 7.0まで: signalシステムコールを利用
(直接 zend_timeout が呼ばれてた)
– 7.1から: zend_signalを利用 (ZEND_SIGNALS)
(zend_timeout_handler)
この中で EG(timed_out) = 1
- 16. ZEND_SIGNALS
• ZendEngineやSAPI,拡張 と 実行環境 の間に作ら
れた signal 処理の中間層
– 環境依存な signal 処理を画一的に扱うための仕組み
– 7.1 から デフォルトで有効
• php スクリプトにおける pcntl のようなものを、
C言語で(コアや拡張向けに) 提供した感じ
– zend_signal によって実行環境に登録されるシグナル
ハンドラは zend_signal_handler_defer に統一さ
れる (シグナルハンドラとして指定した関数はここか
ら間接的に呼ばれる)
- 17. Deferred Signals
• ZEND_SIGNAL_BLOCK_INTERRUPTIONS (=
HANDLE_BLOCK_INTERRUPTIONS) により、
シグナルハンドラの実行を延期することが可
能
– 現状使ってるのは opcache のみ
– 解放は ZEND_SIGNAL_UNBLOCK_INTERRUPTIONS
– シグナルハンドラの実行タイミングを制御するこ
とで、共有メモリ操作時の不安定な動きを解消し
ている(らしい)
– 以前はメモリ操作周りでも利用されていたが、
7.0 でのメモリマネージャ刷新によって不要に
なった?
- 19. まとめ
– pcntl signal
– EG(vm_interrupt)
– Safe timeout handling
– ZEND_SIGNALS
• について話しました
• 7.1 で php における signal 処理はだいぶ大き
く変容します
– おそらく ふつーに php スクリプト書いている人に
は気づかれないような変化。
けど、これにより安定化とパフォーマンス向上が図
られているのです
- 20. 参照
• Zend Signal Handling
– https://wiki.php.net/rfc/zendsignals
– https://github.com/php/php-
src/commit/939875133a2c389d621a9999a8ede3ddbc9b6637
• Asynchronous Signal Handling (without TICKs)
– https://wiki.php.net/rfc/async_signals
– https://github.com/php/php-
src/commit/c03ccfe78d6b13cab9546efb616a42a8f3e8a4e0
• Safe execution timeout handling
– https://www.mail-archive.com/internals@lists.php.net/msg76907.html
– https://github.com/php/php-src/pull/1876
• Enable Zend Signals by Default
– https://www.mail-archive.com/internals@lists.php.net/msg86428.html
Editor's Notes
- process が signal を受け取ると、 pcntl_signal_handler が受け取る。
signal handler は実行できることが限られるため、任意の処理を行えないようにしている。
tick あるいは pcntl_signal_dispatch php 関数が呼ばれると、 pcntl_signal_dispatch C関数が呼ばれ、
pending signal queue から一つずつ 受信した signal 番号を取り出し、signal table に登録されている関数を callback する。
7.1からは、環境が siginfo に対応している場合には siginfo (シグナルの呼び出し元pidやuid 等の詳細情報)も保持する。、
これを array に変換したものが pcntl_signal で設定した callback 関数の第2引数として渡ってくる (まだドキュメントにはない)