PHP

提供: FirstWiki
ナビゲーションに移動 検索に移動

トラブル

php-fpm が OPcache の JIT に原因があって Segmentation Fault を起こすケースの対策

opcache.jit = 1254

これを以下のように変更してください。

opcache.jit = 1205

エラーが発生する原因

PHPの開発元でも 議論 になっているのですが、残念ながら詳細な発生原因までは明らかになっていません。これは確実に再現する環境を作るのが難しいところにあります。

当社のお客様の環境でもこの事象が発生するケースがありましたが、KUSANAGIには「HTTP 502 Bad Gateway」が頻発すると自動的にnginxやphp-fpmを再起動する仕組みがあります。この仕組みによってphp-fpmが再起動するとしばらく発生しなくなるというように、常に発生するわけでもありませんでした。

ここからは私見となりますが、PHP スクリプトファイルの更新が頻繁に行われる環境のように、PHP スクリプト (*.php) と共有メモリ上のキャッシュに差が生じたときに Segmentation Fault が発生するように感じました。

まず、OPcache は PHP スクリプト (*.php) のコンパイル済みバイトコードを共有メモリ上にキャッシュする仕組みです。JIT はこの OPcache のバイトコードを更に直接マシン語に変換する仕組みになっています。

KUSANAGIのデフォルト設定である opcache.jit = 1254 はトレーシング (tracing) モードです。このモードではコードのプロファイリングよって頻繁に実行される部分 (ホットコード) をコンパイルするという動作になります。このプロファイリング時は同じコードと判断したホットコードが、実際に動作する時は同じではなかったことでエラーの原因になったのではないかと推測しています。

なお、対処で変更した opcache.jit = 1205 は関数 (function) モードです。ホットコードを見付けるのではなく、常に PHP スクリプトの読み込み時にコンパイルをするという動作になります。そのため、このエラーが発生しなくなります。

ちなみに opcache.jit = off を指定することで、完全に JIT を無効にすることもできます。しかし、これは推奨しません。理由は後述します。