SlideShare a Scribd company logo
1 of 20
signal の話
或いは
Zend Signals とは何か
2016/12/11
第七回闇PHP勉強会
do_aki
updated 2016-12-13
@do_aki
@do_aki
http://do-aki.net/
signal とは
• UNIX系OS に古くからあるプロセス間通信の
一つ
• プロセスがシグナル(実態は整数) を受信す
ると、あらかじめ設定した処理(シグナルハ
ンドラ)が実行される(乱暴に言えば割り込
みが発生する)
• シグナルハンドラが設定されてないシグナル
は、無視されるかあるいは既定の動きをする
(その多くはプログラムの終了)
php においては
• pcntl 拡張を利用することで signal 処
理を管理することが可能
• pcntl_signal(signo, callback)
pcntl_signal の利用例<?php
declare(ticks=1);
$signal_callback_function = function ($signo) {
echo "receive signal: {$signo}¥n";
exit;
};
pcntl_signal(SIGINT, $signal_callback_function);
while(1) {
sleep(1);
}
// 通常の動きだけでは永久ループ
// Ctrl + C 押下で、 "receive signal: 2" を出力して終了
pcntl による signal 処理
これは単純に
“シグナルを受信したら
callback が実行される”
というものではない
pcntl_signal が行うこと
• signal_table に シグナル番号とコール
バック関数を登録
• 該当シグナル番号に対するシグナルハン
ドラとして pcntl_signal_handler を
(実行環境に対して) 登録
• 実際にコールバック関数を呼ぶのは
pcntl_signal_dispatch
signal handling
pcntl_signal_handler
signo
pcntl_signal_dispatch
SIGHUP funcA
SIGINT funcB
SIGALRM funcC
……
signal table
lookup
&
call
signo
pending signal queue
[receive signal]
[tick or vm_interrupt]
シグナルハンドラの制約
• どんなタイミングであっても呼ばれる可能性
がある
– 当然 php のスタックフレームは無視
• 呼び出し可能なシステムコールが限られる
– man signal 7 を参照
最小限の処理(受信したことの記録) だけ
行い、あとから適切なタイミングでコール
バックを実行(dispatch)している
なので
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 指定忘れるとシグナルコールバックされない
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 される気がする)
dispatch by vm_interrupt
pcntl_signal_handler
pcntl_signal_dispatch
[receive signal]
EG(vm_in
terrupt)
PHP VM
zend_interrupt_function =
pcntl_interrupt_function
[each opcode]
set1
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 を超えたとき
に設定される
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
Safe timeout handling
zend_timeout_
handler
PHP VM
zend_timeout
set1
zend_timeout
~7.0 (or !ZEND_SIGNALS)
7.1~ (with ZEND_SIGNALS)
EG(vm_in
terrupt)
EG(timed
_out)
ZEND_SIGNALS
• ZendEngineやSAPI,拡張 と 実行環境 の間に作ら
れた signal 処理の中間層
– 環境依存な signal 処理を画一的に扱うための仕組み
– 7.1 から デフォルトで有効
• php スクリプトにおける pcntl のようなものを、
C言語で(コアや拡張向けに) 提供した感じ
– zend_signal によって実行環境に登録されるシグナル
ハンドラは zend_signal_handler_defer に統一さ
れる (シグナルハンドラとして指定した関数はここか
ら間接的に呼ばれる)
Deferred Signals
• ZEND_SIGNAL_BLOCK_INTERRUPTIONS (=
HANDLE_BLOCK_INTERRUPTIONS) により、
シグナルハンドラの実行を延期することが可
能
– 現状使ってるのは opcache のみ
– 解放は ZEND_SIGNAL_UNBLOCK_INTERRUPTIONS
– シグナルハンドラの実行タイミングを制御するこ
とで、共有メモリ操作時の不安定な動きを解消し
ている(らしい)
– 以前はメモリ操作周りでも利用されていたが、
7.0 でのメモリマネージャ刷新によって不要に
なった?
ZEND SIGNALS
zend_signal_handler_defer
1 handler1
2 hanlder2
3 hanlder3
……
SIGG(handlers)
zend signal queue
signo
signal blocked
(HANDLE_BLOCK_INTERRUPTIONS)
signal unblocked
HANDLE_UNBLOCK_INTERRUPTIONS
signo
callzend_signal_handler
まとめ
– pcntl signal
– EG(vm_interrupt)
– Safe timeout handling
– ZEND_SIGNALS
• について話しました
• 7.1 で php における signal 処理はだいぶ大き
く変容します
– おそらく ふつーに php スクリプト書いている人に
は気づかれないような変化。
けど、これにより安定化とパフォーマンス向上が図
られているのです
参照
• 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

More Related Content

What's hot

PECL を数えてみた
PECL を数えてみたPECL を数えてみた
PECL を数えてみたy-uti
 
php7's ast
php7's astphp7's ast
php7's astdo_aki
 
php and sapi and zendengine2 and...
php and sapi and zendengine2 and...php and sapi and zendengine2 and...
php and sapi and zendengine2 and...do_aki
 
PECL operator で演算子オーバーロード
PECL operator で演算子オーバーロードPECL operator で演算子オーバーロード
PECL operator で演算子オーバーロードy-uti
 
Zynq VIPを利用したテストベンチ
Zynq VIPを利用したテストベンチZynq VIPを利用したテストベンチ
Zynq VIPを利用したテストベンチMr. Vengineer
 
Php in ruby
Php in rubyPhp in ruby
Php in rubydo_aki
 
LLVM overview 20110122
LLVM overview 20110122LLVM overview 20110122
LLVM overview 20110122nothingcosmos
 
Async design with Unity3D
Async design with Unity3DAsync design with Unity3D
Async design with Unity3DKouji Hosoda
 
あるコンテキストスイッチの話
あるコンテキストスイッチの話あるコンテキストスイッチの話
あるコンテキストスイッチの話nullnilaki
 
Adaptive optimization of JIT compiler
Adaptive optimization of JIT compilerAdaptive optimization of JIT compiler
Adaptive optimization of JIT compilernothingcosmos
 
PHPでマルチスレッド
PHPでマルチスレッドPHPでマルチスレッド
PHPでマルチスレッドkarky7
 
OPcacheの新機能ファイルベースキャッシュの内部実装を読んでみた
OPcacheの新機能ファイルベースキャッシュの内部実装を読んでみたOPcacheの新機能ファイルベースキャッシュの内部実装を読んでみた
OPcacheの新機能ファイルベースキャッシュの内部実装を読んでみたYoshio Hanawa
 
Android デバッグ小ネタ
Android デバッグ小ネタAndroid デバッグ小ネタ
Android デバッグ小ネタl_b__
 
最近の PHP の話
最近の PHP の話最近の PHP の話
最近の PHP の話y-uti
 
ラボユース最終成果報告会(Web公開版)
ラボユース最終成果報告会(Web公開版)ラボユース最終成果報告会(Web公開版)
ラボユース最終成果報告会(Web公開版)Shinichi Awamoto
 
Dive into RTS - another side
Dive into RTS - another sideDive into RTS - another side
Dive into RTS - another sideKiwamu Okabe
 
Synthesijer fpgax 20150201
Synthesijer fpgax 20150201Synthesijer fpgax 20150201
Synthesijer fpgax 20150201Takefumi MIYOSHI
 

What's hot (20)

PECL を数えてみた
PECL を数えてみたPECL を数えてみた
PECL を数えてみた
 
php7's ast
php7's astphp7's ast
php7's ast
 
php and sapi and zendengine2 and...
php and sapi and zendengine2 and...php and sapi and zendengine2 and...
php and sapi and zendengine2 and...
 
PECL operator で演算子オーバーロード
PECL operator で演算子オーバーロードPECL operator で演算子オーバーロード
PECL operator で演算子オーバーロード
 
ZynqMPのQEMU
ZynqMPのQEMUZynqMPのQEMU
ZynqMPのQEMU
 
Zynq VIPを利用したテストベンチ
Zynq VIPを利用したテストベンチZynq VIPを利用したテストベンチ
Zynq VIPを利用したテストベンチ
 
Php in ruby
Php in rubyPhp in ruby
Php in ruby
 
LLVM overview 20110122
LLVM overview 20110122LLVM overview 20110122
LLVM overview 20110122
 
Async design with Unity3D
Async design with Unity3DAsync design with Unity3D
Async design with Unity3D
 
あるコンテキストスイッチの話
あるコンテキストスイッチの話あるコンテキストスイッチの話
あるコンテキストスイッチの話
 
Adaptive optimization of JIT compiler
Adaptive optimization of JIT compilerAdaptive optimization of JIT compiler
Adaptive optimization of JIT compiler
 
PHPでマルチスレッド
PHPでマルチスレッドPHPでマルチスレッド
PHPでマルチスレッド
 
OPcacheの新機能ファイルベースキャッシュの内部実装を読んでみた
OPcacheの新機能ファイルベースキャッシュの内部実装を読んでみたOPcacheの新機能ファイルベースキャッシュの内部実装を読んでみた
OPcacheの新機能ファイルベースキャッシュの内部実装を読んでみた
 
Android デバッグ小ネタ
Android デバッグ小ネタAndroid デバッグ小ネタ
Android デバッグ小ネタ
 
最近の PHP の話
最近の PHP の話最近の PHP の話
最近の PHP の話
 
ttwrite
ttwritettwrite
ttwrite
 
ラボユース最終成果報告会(Web公開版)
ラボユース最終成果報告会(Web公開版)ラボユース最終成果報告会(Web公開版)
ラボユース最終成果報告会(Web公開版)
 
Dive into RTS - another side
Dive into RTS - another sideDive into RTS - another side
Dive into RTS - another side
 
Synthesijer fpgax 20150201
Synthesijer fpgax 20150201Synthesijer fpgax 20150201
Synthesijer fpgax 20150201
 
Das 2015
Das 2015Das 2015
Das 2015
 

Similar to signal の話 或いは Zend Signals とは何か

Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputingNoboru Irieda
 
StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件yaegashi
 
Unixカーネルの設計 7 プロセスの制御
Unixカーネルの設計 7 プロセスの制御Unixカーネルの設計 7 プロセスの制御
Unixカーネルの設計 7 プロセスの制御Norito Agetsuma
 
イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化Gosuke Miyashita
 
Linuxのプロセススケジューラ(Reading the Linux process scheduler)
Linuxのプロセススケジューラ(Reading the Linux process scheduler)Linuxのプロセススケジューラ(Reading the Linux process scheduler)
Linuxのプロセススケジューラ(Reading the Linux process scheduler)Hiraku Toyooka
 
Boost9 session
Boost9 sessionBoost9 session
Boost9 sessionfreedom404
 
CMSI計算科学技術特論B(14) OpenACC・CUDAによるGPUコンピューティング
CMSI計算科学技術特論B(14) OpenACC・CUDAによるGPUコンピューティングCMSI計算科学技術特論B(14) OpenACC・CUDAによるGPUコンピューティング
CMSI計算科学技術特論B(14) OpenACC・CUDAによるGPUコンピューティングComputational Materials Science Initiative
 
【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門 【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門 sandai
 
NGS解析を始めた時にぶつかりがちな小さい壁あれこれ
NGS解析を始めた時にぶつかりがちな小さい壁あれこれNGS解析を始めた時にぶつかりがちな小さい壁あれこれ
NGS解析を始めた時にぶつかりがちな小さい壁あれこれDNA Data Bank of Japan center
 
8 並列計算に向けた pcセッティング
8 並列計算に向けた pcセッティング8 並列計算に向けた pcセッティング
8 並列計算に向けた pcセッティングTakeshi Takaishi
 
PyOpenCLによるGPGPU入門
PyOpenCLによるGPGPU入門PyOpenCLによるGPGPU入門
PyOpenCLによるGPGPU入門Yosuke Onoue
 
MINCS – containers in the shell script
MINCS – containers in the shell scriptMINCS – containers in the shell script
MINCS – containers in the shell scriptMasami Hiramatsu
 
【学習メモ#9th】12ステップで作る組込みOS自作入門
【学習メモ#9th】12ステップで作る組込みOS自作入門 【学習メモ#9th】12ステップで作る組込みOS自作入門
【学習メモ#9th】12ステップで作る組込みOS自作入門 sandai
 
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)inaz2
 
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解するそうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解するshigeki_ohtsu
 
Spmv9forpublic
Spmv9forpublicSpmv9forpublic
Spmv9forpublicT2C_
 
とある帽子の大蛇料理Ⅱ
とある帽子の大蛇料理Ⅱとある帽子の大蛇料理Ⅱ
とある帽子の大蛇料理ⅡMasami Ichikawa
 

Similar to signal の話 或いは Zend Signals とは何か (20)

Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputing
 
StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件
 
Unixカーネルの設計 7 プロセスの制御
Unixカーネルの設計 7 プロセスの制御Unixカーネルの設計 7 プロセスの制御
Unixカーネルの設計 7 プロセスの制御
 
SystemV IPC
SystemV IPCSystemV IPC
SystemV IPC
 
イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化イベント駆動プログラミングとI/O多重化
イベント駆動プログラミングとI/O多重化
 
Linuxのプロセススケジューラ(Reading the Linux process scheduler)
Linuxのプロセススケジューラ(Reading the Linux process scheduler)Linuxのプロセススケジューラ(Reading the Linux process scheduler)
Linuxのプロセススケジューラ(Reading the Linux process scheduler)
 
Boost9 session
Boost9 sessionBoost9 session
Boost9 session
 
CMSI計算科学技術特論B(14) OpenACC・CUDAによるGPUコンピューティング
CMSI計算科学技術特論B(14) OpenACC・CUDAによるGPUコンピューティングCMSI計算科学技術特論B(14) OpenACC・CUDAによるGPUコンピューティング
CMSI計算科学技術特論B(14) OpenACC・CUDAによるGPUコンピューティング
 
【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門 【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門
 
NGS解析を始めた時にぶつかりがちな小さい壁あれこれ
NGS解析を始めた時にぶつかりがちな小さい壁あれこれNGS解析を始めた時にぶつかりがちな小さい壁あれこれ
NGS解析を始めた時にぶつかりがちな小さい壁あれこれ
 
8 並列計算に向けた pcセッティング
8 並列計算に向けた pcセッティング8 並列計算に向けた pcセッティング
8 並列計算に向けた pcセッティング
 
Rの高速化
Rの高速化Rの高速化
Rの高速化
 
PyOpenCLによるGPGPU入門
PyOpenCLによるGPGPU入門PyOpenCLによるGPGPU入門
PyOpenCLによるGPGPU入門
 
MINCS – containers in the shell script
MINCS – containers in the shell scriptMINCS – containers in the shell script
MINCS – containers in the shell script
 
【学習メモ#9th】12ステップで作る組込みOS自作入門
【学習メモ#9th】12ステップで作る組込みOS自作入門 【学習メモ#9th】12ステップで作る組込みOS自作入門
【学習メモ#9th】12ステップで作る組込みOS自作入門
 
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
 
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解するそうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する
そうだったのか! よくわかる process.nextTick() node.jsのイベントループを理解する
 
Spmv9forpublic
Spmv9forpublicSpmv9forpublic
Spmv9forpublic
 
Gstreamer Basics
Gstreamer BasicsGstreamer Basics
Gstreamer Basics
 
とある帽子の大蛇料理Ⅱ
とある帽子の大蛇料理Ⅱとある帽子の大蛇料理Ⅱ
とある帽子の大蛇料理Ⅱ
 

More from do_aki

Tritonn から Elasticsearch への移行話
Tritonn から Elasticsearch への移行話Tritonn から Elasticsearch への移行話
Tritonn から Elasticsearch への移行話do_aki
 
再考:列挙型
再考:列挙型再考:列挙型
再考:列挙型do_aki
 
Writing php extensions in golang
Writing php extensions in golangWriting php extensions in golang
Writing php extensions in golangdo_aki
 
N対1 レプリケーション + Optimizer Hint
N対1 レプリケーション + Optimizer HintN対1 レプリケーション + Optimizer Hint
N対1 レプリケーション + Optimizer Hintdo_aki
 
20150212 プレゼンテーションzen
20150212 プレゼンテーションzen20150212 プレゼンテーションzen
20150212 プレゼンテーションzendo_aki
 
MySQL Casual Talks 7 「N:1 レプリケーション ~進捗どうですか?~」
MySQL Casual Talks 7 「N:1 レプリケーション ~進捗どうですか?~」MySQL Casual Talks 7 「N:1 レプリケーション ~進捗どうですか?~」
MySQL Casual Talks 7 「N:1 レプリケーション ~進捗どうですか?~」do_aki
 
20141017 introduce razor
20141017 introduce razor20141017 introduce razor
20141017 introduce razordo_aki
 
20141011 mastering mysqlnd
20141011 mastering mysqlnd20141011 mastering mysqlnd
20141011 mastering mysqlnddo_aki
 
php in ruby
php in rubyphp in ruby
php in rubydo_aki
 
PHP から Groonga を使うにはこんなコードになるよ!
PHP から Groonga を使うにはこんなコードになるよ!PHP から Groonga を使うにはこんなコードになるよ!
PHP から Groonga を使うにはこんなコードになるよ!do_aki
 
N:1 Replication meets MHA
N:1 Replication meets MHAN:1 Replication meets MHA
N:1 Replication meets MHAdo_aki
 
Php radomize
Php radomizePhp radomize
Php radomizedo_aki
 
セキュアそうでセキュアじゃない少しセキュアな気分になれるmysql_config_editor
セキュアそうでセキュアじゃない少しセキュアな気分になれるmysql_config_editorセキュアそうでセキュアじゃない少しセキュアな気分になれるmysql_config_editor
セキュアそうでセキュアじゃない少しセキュアな気分になれるmysql_config_editordo_aki
 
マスタN対スレーブ1レプリケーションの作り方 ~あれから~
マスタN対スレーブ1レプリケーションの作り方 ~あれから~マスタN対スレーブ1レプリケーションの作り方 ~あれから~
マスタN対スレーブ1レプリケーションの作り方 ~あれから~do_aki
 
Immortal
ImmortalImmortal
Immortaldo_aki
 
Excel is image viewer
Excel is image viewerExcel is image viewer
Excel is image viewerdo_aki
 
A bridge between php and ruby
A bridge between php and ruby A bridge between php and ruby
A bridge between php and ruby do_aki
 
Ruby and comparison_and...php
Ruby and comparison_and...phpRuby and comparison_and...php
Ruby and comparison_and...phpdo_aki
 
Sore php
Sore phpSore php
Sore phpdo_aki
 
Ruby enumerable source code reading
Ruby enumerable source code readingRuby enumerable source code reading
Ruby enumerable source code readingdo_aki
 

More from do_aki (20)

Tritonn から Elasticsearch への移行話
Tritonn から Elasticsearch への移行話Tritonn から Elasticsearch への移行話
Tritonn から Elasticsearch への移行話
 
再考:列挙型
再考:列挙型再考:列挙型
再考:列挙型
 
Writing php extensions in golang
Writing php extensions in golangWriting php extensions in golang
Writing php extensions in golang
 
N対1 レプリケーション + Optimizer Hint
N対1 レプリケーション + Optimizer HintN対1 レプリケーション + Optimizer Hint
N対1 レプリケーション + Optimizer Hint
 
20150212 プレゼンテーションzen
20150212 プレゼンテーションzen20150212 プレゼンテーションzen
20150212 プレゼンテーションzen
 
MySQL Casual Talks 7 「N:1 レプリケーション ~進捗どうですか?~」
MySQL Casual Talks 7 「N:1 レプリケーション ~進捗どうですか?~」MySQL Casual Talks 7 「N:1 レプリケーション ~進捗どうですか?~」
MySQL Casual Talks 7 「N:1 レプリケーション ~進捗どうですか?~」
 
20141017 introduce razor
20141017 introduce razor20141017 introduce razor
20141017 introduce razor
 
20141011 mastering mysqlnd
20141011 mastering mysqlnd20141011 mastering mysqlnd
20141011 mastering mysqlnd
 
php in ruby
php in rubyphp in ruby
php in ruby
 
PHP から Groonga を使うにはこんなコードになるよ!
PHP から Groonga を使うにはこんなコードになるよ!PHP から Groonga を使うにはこんなコードになるよ!
PHP から Groonga を使うにはこんなコードになるよ!
 
N:1 Replication meets MHA
N:1 Replication meets MHAN:1 Replication meets MHA
N:1 Replication meets MHA
 
Php radomize
Php radomizePhp radomize
Php radomize
 
セキュアそうでセキュアじゃない少しセキュアな気分になれるmysql_config_editor
セキュアそうでセキュアじゃない少しセキュアな気分になれるmysql_config_editorセキュアそうでセキュアじゃない少しセキュアな気分になれるmysql_config_editor
セキュアそうでセキュアじゃない少しセキュアな気分になれるmysql_config_editor
 
マスタN対スレーブ1レプリケーションの作り方 ~あれから~
マスタN対スレーブ1レプリケーションの作り方 ~あれから~マスタN対スレーブ1レプリケーションの作り方 ~あれから~
マスタN対スレーブ1レプリケーションの作り方 ~あれから~
 
Immortal
ImmortalImmortal
Immortal
 
Excel is image viewer
Excel is image viewerExcel is image viewer
Excel is image viewer
 
A bridge between php and ruby
A bridge between php and ruby A bridge between php and ruby
A bridge between php and ruby
 
Ruby and comparison_and...php
Ruby and comparison_and...phpRuby and comparison_and...php
Ruby and comparison_and...php
 
Sore php
Sore phpSore php
Sore php
 
Ruby enumerable source code reading
Ruby enumerable source code readingRuby enumerable source code reading
Ruby enumerable source code reading
 

signal の話 或いは Zend Signals とは何か

  • 1. signal の話 或いは Zend Signals とは何か 2016/12/11 第七回闇PHP勉強会 do_aki updated 2016-12-13
  • 3. signal とは • UNIX系OS に古くからあるプロセス間通信の 一つ • プロセスがシグナル(実態は整数) を受信す ると、あらかじめ設定した処理(シグナルハ ンドラ)が実行される(乱暴に言えば割り込 みが発生する) • シグナルハンドラが設定されてないシグナル は、無視されるかあるいは既定の動きをする (その多くはプログラムの終了)
  • 4. php においては • pcntl 拡張を利用することで signal 処 理を管理することが可能 • pcntl_signal(signo, callback)
  • 5. pcntl_signal の利用例<?php declare(ticks=1); $signal_callback_function = function ($signo) { echo "receive signal: {$signo}¥n"; exit; }; pcntl_signal(SIGINT, $signal_callback_function); while(1) { sleep(1); } // 通常の動きだけでは永久ループ // Ctrl + C 押下で、 "receive signal: 2" を出力して終了
  • 6. pcntl による signal 処理 これは単純に “シグナルを受信したら callback が実行される” というものではない
  • 7. pcntl_signal が行うこと • signal_table に シグナル番号とコール バック関数を登録 • 該当シグナル番号に対するシグナルハン ドラとして pcntl_signal_handler を (実行環境に対して) 登録 • 実際にコールバック関数を呼ぶのは pcntl_signal_dispatch
  • 8. signal handling pcntl_signal_handler signo pcntl_signal_dispatch SIGHUP funcA SIGINT funcB SIGALRM funcC …… signal table lookup & call signo pending signal queue [receive signal] [tick or vm_interrupt]
  • 9. シグナルハンドラの制約 • どんなタイミングであっても呼ばれる可能性 がある – 当然 php のスタックフレームは無視 • 呼び出し可能なシステムコールが限られる – man signal 7 を参照 最小限の処理(受信したことの記録) だけ 行い、あとから適切なタイミングでコール バックを実行(dispatch)している なので
  • 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 される気がする)
  • 12. dispatch by vm_interrupt pcntl_signal_handler pcntl_signal_dispatch [receive signal] EG(vm_in terrupt) PHP VM zend_interrupt_function = pcntl_interrupt_function [each opcode] set1
  • 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
  • 15. Safe timeout handling zend_timeout_ handler PHP VM zend_timeout set1 zend_timeout ~7.0 (or !ZEND_SIGNALS) 7.1~ (with ZEND_SIGNALS) EG(vm_in terrupt) EG(timed _out)
  • 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 でのメモリマネージャ刷新によって不要に なった?
  • 18. ZEND SIGNALS zend_signal_handler_defer 1 handler1 2 hanlder2 3 hanlder3 …… SIGG(handlers) zend signal queue signo signal blocked (HANDLE_BLOCK_INTERRUPTIONS) signal unblocked HANDLE_UNBLOCK_INTERRUPTIONS signo callzend_signal_handler
  • 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

  1. 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引数として渡ってくる (まだドキュメントにはない)