Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segmentation fault in PHP 8.1 #8461

Closed
oleg-st opened this issue Apr 29, 2022 · 8 comments
Closed

Segmentation fault in PHP 8.1 #8461

oleg-st opened this issue Apr 29, 2022 · 8 comments

Comments

@oleg-st
Copy link
Contributor

oleg-st commented Apr 29, 2022

Description

The problem is quite difficult to reproduce.
Need to change php files when running specific application in php-fpm.

Steps to reproduce:

  1. Turn on JIT, Opcache
opcache.jit_buffer_size=100M
opcache.jit=1255
  1. Extract
    bugphp.zip
  2. Use ab to execute run.php from bugphp.zip:
ab -n 5000 -c 20 http://localhost/run.php

Application touches UniqueList.php to make it modified for the OPcache.

Segmentation faults:

[29-Apr-2022 15:07:30] NOTICE: ready to handle connections
[29-Apr-2022 15:07:33] WARNING: [pool www] child 338824 exited on signal 11 (SIGSEGV - core dumped) after 2.980459 seconds from start
[29-Apr-2022 15:07:33] NOTICE: [pool www] child 338841 started
[29-Apr-2022 15:07:33] WARNING: [pool www] child 338827 exited on signal 11 (SIGSEGV - core dumped) after 2.980157 seconds from start
[29-Apr-2022 15:07:33] NOTICE: [pool www] child 338842 started
[29-Apr-2022 15:07:33] WARNING: [pool www] child 338826 exited on signal 11 (SIGSEGV - core dumped) after 2.999109 seconds from start

Backtrace:

#0  0x00000000008a47d1 in ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_CONST_HANDLER ()
    at /home/Oleg.Stepanischev/php-src/Zend/zend_vm_execute.h:33346
#1  0x00000000008cdcd3 in execute_ex (ex=0x7fb8c7c14020) at /home/Oleg.Stepanischev/php-src/Zend/zend_vm_execute.h:58689
#2  0x00000000008cf41b in zend_execute (op_array=0x7fb8c7c67000, return_value=0x0)
    at /home/Oleg.Stepanischev/php-src/Zend/zend_vm_execute.h:60123
#3  0x00000000008231b3 in zend_execute_scripts (type=8, retval=0x0, file_count=3)
    at /home/Oleg.Stepanischev/php-src/Zend/zend.c:1792
#4  0x000000000078bbd4 in php_execute_script (primary_file=0x7ffdc50da360) at /home/Oleg.Stepanischev/php-src/main/main.c:2538
#5  0x00000000009901d9 in main (argc=2, argv=0x7ffdc50da578) at /home/Oleg.Stepanischev/php-src/sapi/fpm/fpm/fpm_main.c:1914

Bisect found the commit that contains the problem: 4b79dba
Disabling inheritance cache solves the problem.
The UniqueList class has a child class UniqueListLast that uses some of the parent class's constants. And the modification of the parent class somehow leads to the problem.

Possible related to #7817

PHP Version

PHP 8.1

Operating System

AlmaLinux release 8.5 (Arctic Sphynx)

@meinemitternacht
Copy link

I'm pretty sure this is the source of the problems in #7817. In our application (embedded hardware), there are several PHP files that are generated by other C programs which are overwritten often.

@bolknote
Copy link
Contributor

Wow! Great job, Oleg!

@oleg-st
Copy link
Contributor Author

oleg-st commented May 4, 2022

After some research, I found that the problem occurs here https://github.com/php/php-src/blob/PHP-8.1/ext/opcache/jit/zend_jit_x86.dasc#L10044
func->op_array.run_time_cache__ptr changes when the file with the called function is reloaded. I don't know if it was intended or not. This causes the run_time_cache to be loaded incorrectly.

@arnaud-lb
Copy link
Member

I confirm this. The run_time_cache__ptr of the sub class constructor changes when the parent class is recompiled.

The crash happens because the old run_time_cache offset is still used by the generated code.

Change of the run_time_cache__ptr happens during zend_do_link_class, when the inheritance cache is persisted.

Reverting the changes made by JIT on the op array would fix the issue. I think that we are not supposed to reuse the JIT code here.

@oleg-st
Copy link
Contributor Author

oleg-st commented May 5, 2022

A simple fix is to remove 2 branches with specific cases and leave one generic:
https://github.com/php/php-src/blob/PHP-8.1/ext/opcache/jit/zend_jit_x86.dasc#L10069

It's also strange that the second branch uses run_time_cache__ptr as an offset, but the first branch has already fully covered this case.

To remove the JIT code in this case, I think we need to remove the JIT code of all callers when the callee code changes.

@oleg-st
Copy link
Contributor Author

oleg-st commented May 12, 2022

Tested with #8535, everything works fine for me

@rs-orlov
Copy link

rs-orlov commented Sep 8, 2023

@oleg-st what do you mean by "Disabling inheritance cache ...", did you just dropped commit and built php without it? Or is there a reasonably small patch which makes inheritance cache effectively disabled?

We have another issue with inheritance cache. It blocks us from upgrading php version. Considering amount of time issue hangs without any movement, disabling inheritance cache (even by patching php) seems to be not so bad alternative.

@oleg-st
Copy link
Contributor Author

oleg-st commented Sep 10, 2023

@rs-orlov
This can be done by commenting out these 2 lines:

zend_inheritance_cache_get = zend_accel_inheritance_cache_get;
zend_inheritance_cache_add = zend_accel_inheritance_cache_add;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants
@ramsey @arnaud-lb @bolknote @rs-orlov @meinemitternacht @oleg-st and others