PHP でシグナルを扱うにはプロセス制御を利用する。
その際に必要なticks
関数の設定についてメモする。
その前に
pcntl が使えるか確認する。以下で実行可能か確認しておく。
1
2
|
$ php -i | awk /[p]cntl\ support/
pcntl support => enabled
|
OSXで標準で入っているのはコンパイルオプション--enable-pcntl
が有効になってなかった。
公式に従ってインストールしてしまう
かphpenv
で有効なバージョンを入れる。phpenv
でインストールした。
1
2
3
4
|
# phpenvでbuildする時のオプションの確認
$ awk /pcntl/ ~/.phpenv/plugins/php-build/share/php-build/default_configure_options
--enable-pcntl
$ phpenv intall 5.5.5
|
declare(ticks = 1)を有効にする
シグナルハンドラの登録はpcntl-signalを使う。
で 4.3.0以降はdeclare(ticks = 1);
をコードブロックに記述しないと動かない。
ticks
関数のpcntl_signal_dispatch
が呼ばれることでシグナルハンドラが叩かれる仕組みになっているのだけれど、
ticksは効率が悪いって事で、
4.3.0以降ではdeclare
による明記が必要になったため。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
<?php
// test.php
declare(ticks = 1);
pcntl_signal(SIGHUP, handler);
function handler($signo) {
echo 'in '. __FUNCTION__. PHP_EOL;
exit(1);
}
while (true) {
echo 'in loop. '. __FILE__. PHP_EOL;
sleep(1);
}
動かした感じ。
```bash
$ php -d open_basedir=/ test.php
in loop test.php
in loop test.php
in loop test.php
...
# 別ターミナルで
$ kill -s 1 $PID
# 動いてた方が応えている
in handler
|
declareの位置を注意する
グローバル環境でdeclare
設定されると呼び出されたコードブロックの中でも設定は有効。
だけど呼び出された側のグローバル環境で設定しても呼び出し元には影響しない。
なので下のコードはSIGHUPを受け取ってくれない。
1
2
3
4
5
6
7
8
9
10
11
12
|
<?php
// test.php
pcntl_signal(SIGHUP, handler);
function handler($signo) {
echo 'in '. __FUNCTION__. PHP_EOL;
exit(1);
}
require 'required.php';
while (true) {
echo 'in loop. '. __FILE__. PHP_EOL;
sleep(1);
}
|
1
2
3
|
<?php
// required.php
declare(ticks = 1);
|