問題
PHP 8.0 以降でNew Relic PHP エージェント (バージョン 10.18.0.8 以降) が有効になっている場合、サイトでセグメンテーション エラーが発生します。
説明
PHP の Observer API には現在、セグメンテーション エラーを引き起こす可能性のあるバグがいくつかあります。 New Relic PHPエージェントは、エージェント バージョン 10.18 以降、PHP 8.0 以降でアプリケーションをインストゥルメントするために OAPI を利用します。 これらのセグメント エラーは、エージェントが有効な場合にのみ発生します。 これは、PHP の OAPI コードパスはオブザーバーがフックされている場合にのみ実行され、おそらく、環境内で OAPI にフックされているのはNew Relic PHP エージェントだけであるためです。
トレース
このような状況では、スタックトレースは比較的一貫しているように見えます。 いつものように、上部にnr
致命的なシグナル ハンドラーが表示されます。 nr_php_fatal_signal_handler
上のスタック内のすべてのものは、PHP エージェントのインストール時にセグメンテーション フォールトとして常に存在します。これは、ロギングの目的でフォールトを捕捉するためです。 次に、シグナル ハンドラーがzend_observer_fcall_end_all
の間に呼び出されたことがわかります。 これは、登録されているすべてのオブザーバーを呼び出そうとするときに PHP が無効なメモリにアクセスした場合に発生します。 シグナル ハンドラーの前にNew Relicコードがまったく表示されずにスタックトレースに zend_observer_*
が表示される場合は、PHP に問題があるかどうかについて疑問が生じるはずです。
0 nr_php_backtrace_get_call_site () at php_stack.c:220
1 nr_php_frame_info () at php_stack.c:267
2 nr_php_backtrace_fd () at php_stack.c:462
3 0x00007fa6d6df026c in nr_php_fatal_signal_handler () at php_minit.c:740
<signal handler called>
5 0x00007fa6db184c63 in zend_observer_fcall_end_all () from libphp8.2.so
6 0x00007fa6db081abd in php_request_shutdown () from libphp8.2.so
zend_test
問題が PHP なのかエージェントなのかをテストできます。 PHP には、テスト オブザーバーを備えたzend_test
という組み込み拡張機能があります。 これを有効にすると(エージェントを無効にしながら)、OAPI コードパスをエージェント以外で実行できるようになります。 これをテストする手順は次のとおりです。
newrelic.enabled=0
を設定してエージェントを完全に無効にします。 ここでテストして、実際に無効になっていることを確認します。- PHP拡張機能
zend_test
を有効にします。 これは、以下に示すように Dockerfile を変更することで実行できます。 ini
設定をzend_test.observer.enabled=1
とzend_test.observer.observe_all=1
に設定します。 これにより、PHP のオブザーバー API が有効になります。- この状況で問題が再現されるかどうかを確認します。
PHP dockerイメージを使用する Debian の例を次に示します。
FROM php:8.0
RUN apt update && apt install -y libxml2-dev && \ EXTRA_CFLAGS="$(xml2-config --cflags) -I/usr/src/php" docker-php-ext-install zend_test
RUN echo "zend_test.observer.enabled=1" >> $(php-config --ini-dir)/docker-php-ext-zend_test.iniRUN echo "zend_test.observer.observe_all=1" >> $(php-config --ini-dir)/docker-php-ext-zend_test.ini
以下は、Alpine PHP dockerイメージを使用した例です。
FROM php:8.0-alpine
RUN apk add --no-cache libxml2-dev && \ EXTRA_CFLAGS="$(xml2-config --cflags) -I/usr/src/php" docker-php-ext-install zend_test
RUN echo "zend_test.observer.enabled=1" >> $(php-config --ini-dir)/docker-php-ext-zend_test.iniRUN echo "zend_test.observer.observe_all=1" >> $(php-config --ini-dir)/docker-php-ext-zend_test.ini
拡張機能が上記の指示どおりにインストールされ、有効になっている場合のphpinfo()
出力の例を次に示します。
zend_test
zend_test extension => enabled
Directive => Local Value => Master Valuezend_test.limit_copy_file_range => -1 => -1zend_test.not_empty_str_test => val => valzend_test.observe_opline_in_zendmm => Off => Offzend_test.observer.enabled => On => Onzend_test.observer.execute_internal => Off => Offzend_test.observer.fiber_destroy => Off => Offzend_test.observer.fiber_init => Off => Offzend_test.observer.fiber_switch => Off => Offzend_test.observer.observe_all => On => Onzend_test.observer.observe_declaring => Off => Offzend_test.observer.observe_function_names => no value => no valuezend_test.observer.observe_functions => Off => Offzend_test.observer.observe_includes => Off => Offzend_test.observer.show_init_backtrace => Off => Offzend_test.observer.show_opcode => Off => Offzend_test.observer.show_opcode_in_user_handler => no value => no valuezend_test.observer.show_output => On => Onzend_test.observer.show_return_type => Off => Offzend_test.observer.show_return_value => Off => Offzend_test.print_stderr_mshutdown => Off => Offzend_test.quantity_value => 0 => 0zend_test.register_passes => Off => Offzend_test.replace_zend_execute_ex => Off => Offzend_test.str_test => no value => no value
既知の再現と修正の追跡
OAPI およびセグメンテーション エラーに関連する問題を示すこのphp-src ページを確認してください。
関連する修正がリリースされたらすぐに受け取るために、最新の PHP バージョンに更新することをお勧めします。