문제
뉴렐릭 PHP 에이전트(버전 10.18.0.8 이상)가 PHP 8.0 이상에서 활성화된 경우 사이트에서 세그먼테이션 오류가 발생합니다.
설명
PHP의 Observer API에는 현재 세그먼테이션 오류를 일으킬 수 있는 몇 가지 버그가 있습니다. 뉴렐릭 PHP 에이전트는 에이전트 버전 10.18부터 PHP 8.0+에서 축소된 OAPI를 활용합니다. 이러한 세그 폴트는 에이전트가 활성화된 경우에만 발생합니다. PHP의 OAPI 코드 경로는 관찰자가 연결된 경우에만 실행되고, 모든 가능성에서 뉴렐릭 PHP 에이전트가 해당 환경에서 OAPI에 연결된 유일한 것이기 때문입니다.
트레이스
이러한 상황에서는 스택 추적이 비교적 일관된 것으로 보입니다. 우리가 보는 것은 항상 그렇듯이 맨 위에 있는 nr
치명적인 신호 처리기입니다. PHP 에이전트가 설치되면 nr_php_fatal_signal_handler
위의 스택에 있는 모든 내용은 세그먼테이션 오류가 발생할 가능성이 항상 있으므로 로깅 목적으로 오류를 포착합니다. 그런 다음, zend_observer_fcall_end_all
동안 신호 핸들러가 호출되었음을 알 수 있습니다. 이는 PHP가 등록된 모든 관찰자를 호출하려고 할 때 잘못된 메모리에 액세스할 때 발생합니다. 신호 처리기 앞에 뉴렐릭 코드 없이 트럭 추적에서 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의 Observer 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 버전으로 업데이트하는 것이 좋습니다.