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

石川英典

プライム・ストラテジーの「KUSANAGI」は、PHPのOPcacheのJITによって「Segmentation Fault」を起こす問題に対する対処法を紹介。502エラーが頻発した時点で該当する可能性があり、その場合、OPcacheのJIT設定を変更し、php-fpmを再起動することでエラーが発生しなくなる。詳細な発生原因は不明だが、PHPスクリプトファイルの頻繁な更新によりキャッシュとの差が生じるとエラーが発生することが示唆されている。設定変更によるパフォーマンスの影響も報告されており、初期設定のトレーシングモードが最も性能が高い一方で、エラーが発生した場合は関数モードへの変更が推奨されている。

プライム・ストラテジー「KUSANAGI」開発チームの石川です。

今回は ユーザーフォーラムの投稿 に問い合わせが寄せられたことがある 「php-fpm が OPcache の JIT に原因があって Segmentation Fault を起こすケース」 について、確認方法と対処方法、そして原因などを紹介します。

いきなり難しい言葉が4つも出てきたので、まずはこちらから説明します。

  • php-fpm: PHP をウェブサーバにおいて効率よく動作させる仕組み (FastCGI Process Manager) です。KUSANAGIは nginx / httpd の両方において、php-fpmで動作させています。
  • OPcache: PHP がスクリプト (*.php) のコンパイル済みバイトコードを共有メモリ上にキャッシュすることで、PHPの実行を高速化する仕組みです。KUSANAGIはデフォルトで有効化しています。
  • JIT: PHP 8.0より導入された、ジャストインタイム (Just In Time) コンパイラという PHP を速く動作させるための仕組みです。詳細は「PHP重鎮の廣川氏によるコラム」を参照ください。KUSANAGIはデフォルトで有効化しています。
  • Segmentation Fault: ソフトウェア実行時に発生するエラーの1つです。プロセスが異常終了します。

PHP重鎮の廣川氏によるコラム:第8回第14回

発生する現象

ユーザが直接的に見る現象としては、ウェブサイトで「HTTP 502 Bad Gateway」がエラーとして表示されます。

502 Bad Gateway

nginx

ウェブサイトの負荷が高い状態であったり、WordPress等の自動更新が行われている場合にも同様のエラーが表示される場合があります。

しかし、「HTTP 502 Bad Gateway」が継続的 (1時間以上) に発生する場合はこのケースに該当する可能性があります。

確認方法

ウェブサーバのログ

まずは「HTTP 502 Bad Gateway」が発生したウェブサイトのプロファイルにあるウェブサーバのログを確認しましょう。

使用しているウェブサーバによって異なるので、どちらが実行されているかは kusanagi status コマンド で確認してください。

  • nginxの場合: /home/kusanagi/プロファイル名/log/nginx/access.log または /home/kusanagi/プロファイル名/log/nginx/ssl_access.log
  • httpdの場合: /home/kusanagi/プロファイル名/log/httpd/access.log または /home/kusanagi/プロファイル名/log/httpd/ssl_access.log

以下のように「HTTP 502 Bad Gateway」が発生したログが出力されます。

0.002 - - (IPアドレス) - - [28/Feb/2023:16:42:59 +0900] "GET / HTTP/2.0" 502 552 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" "-"

php-fpmのログ

次にphp-fpmのログ /var/opt/kusanagi/log/php-fpm/error.log を確認します。

以下のように Segmentation Fault「signal 11(SIGSEGV)」が発生したログが出力されます。継続的に発生する場合は、このようなログが複数出力されています。

[28-Feb-2023 16:42:59] WARNING: [pool www] child 392282 exited on signal 11 (SIGSEGV) after 24469.890975 seconds from start
[28-Feb-2023 16:42:59] NOTICE: [pool www] child 404335 started

対処方法

OPcacheのJITに関する設定を変更する必要があります。

/etc/opt/kusanagi/php.d/extensions/10-opcache.ini のKUSANAGI 9のデフォルト値は以下のようになっています。 (該当箇所のみ抜粋)

opcache.jit = 1254

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

opcache.jit = 1205

その後にphp-fpmを再起動することで変更が反映されます。 kusanagi php コマンドを実行してください。

$ kusanagi php
php completed.

エラーが発生する原因

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 を無効にすることもできます。しかし、これは推奨しません。理由は後述します。

設定変更による性能差

さて、エラーが発生する可能性があるのであれば、初めから opcache.jit = 1205 (関数モード) をデフォルトにすればよい、と思うかもしれません。

KUSANAGI が opcache.jit = 1254 (トレーシングモード) をデフォルトにしているのは、トレーシングモードと関数モードで性能に差があるためです。

以下は当社のテスト環境において、インストールしたばかりのWordPressで性能を比較したものになります。

opcache.jitトレーシングモードとの比較
トレーシングモード100.00%
関数モード101.89%
無効142.58%
  • KUSANAGI 9 (CentOS Stream 8)
  • Microsoft Azure 東日本リージョン D4as_v4インスタンス 32GB Premium SSD LRS
  • PHP 8.1.16
  • 30多重におけるHTTPS 1リクエストの処理時間の比較

このようにトレーシングモードと比較して、関数モードでは数パーセント、無効にした場合には40%以上の性能劣化が見られました。そのため、KUSANAGIのデフォルトであるトレーシングモードのままにしておき、このケースのエラーが発生した場合にのみ関数モードに変えることを推奨します。

実例から学ぶ、OSSコミュニティに不具合の報告を行う前に知っておきたいこと >>

関連記事

Webサイト運用の課題解決事例100選 プレゼント

Webサイト運用の課題を弊社プロダクトで解決したお客様にインタビュー取材を行い、100の事例を108ページに及ぶ事例集としてまとめました。

・100事例のWebサイト運用の課題と解決手法、解決後の直接、間接的効果がわかる

・情報通信、 IT、金融、メディア、官公庁、学校などの業種ごとに事例を確認できる

・特集では1社の事例を3ページに渡り背景からシステム構成まで詳解