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

Segfault when using opcache and bootstrap file #266

Open
JanTvrdik opened this issue Feb 25, 2023 · 8 comments
Open

Segfault when using opcache and bootstrap file #266

JanTvrdik opened this issue Feb 25, 2023 · 8 comments

Comments

@JanTvrdik
Copy link

JanTvrdik commented Feb 25, 2023

Full isolated reproduction example:
https://github.com/JanTvrdik/php-ext-parallel-segfault

Step to reproduce the segfault

Run the following command:

docker build . -t segfault && docker run --rm -ti segfault

Known requirements to trigger segfault

  • bootstrap file must be used (but can be empty)
  • opcache must be enabled
  • PHP 8.2

GDB output

(gdb) run run.php
Starting program: /usr/local/bin/php run.php
warning: Error disabling address space randomization: Operation not permitted
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7f6b10723700 (LWP 454)]
[New Thread 0x7f6b0fbff700 (LWP 455)]
[New Thread 0x7f6b0efff700 (LWP 456)]
[New Thread 0x7f6b0e3ff700 (LWP 457)]
[New Thread 0x7f6b0d7ff700 (LWP 458)]
[New Thread 0x7f6b0cbff700 (LWP 459)]

Thread 6 "php" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7f6b0d7ff700 (LWP 458)]
0x000055bf0f607297 in ?? ()
(gdb) bt
#0  0x000055bf0f607297 in ?? ()
#1  0x000055bf0f609a06 in zend_do_link_class ()
#2  0x000055bf0f547c43 in zend_bind_class_in_slot ()
#3  0x000055bf0f547d6e in do_bind_class ()
#4  0x000055bf0f5a63d5 in ?? ()
#5  0x000055bf0f5da3f5 in execute_ex ()
#6  0x000055bf0f5616a4 in zend_call_function ()
#7  0x000055bf0f561b4d in zend_call_known_function ()
#8  0x000055bf0f432c9a in ?? ()
#9  0x000055bf0f560755 in zend_lookup_class_ex ()
#10 0x000055bf0f58aa85 in ?? ()
#11 0x000055bf0f5dd308 in execute_ex ()
#12 0x00007f6b1125dbd7 in php_parallel_scheduler_run (frame=0x7f6b0cc14020, runtime=<optimized out>) at /tmp/pear/temp/parallel/src/scheduler.c:316
#13 0x00007f6b1125e1bd in php_parallel_thread (arg=0x7f6b1105c5a0) at /tmp/pear/temp/parallel/src/scheduler.c:486
#14 0x00007f6b146f1ea7 in start_thread (arg=<optimized out>) at pthread_create.c:477
#15 0x00007f6b13e3ea2f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
@JanTvrdik
Copy link
Author

JanTvrdik commented Feb 25, 2023

Running the code with PHP 8.1 does result in the same fatal error, but it does not segfault.

Fatal error: Environment cannot implement - it is not an interface in /src/Environment.php on line 3

Running the code with PHP 8.0 works without any issues.

@michael-rubel
Copy link

michael-rubel commented Oct 25, 2023

Very strange. I had a similar issue on PHP 8.2. I tried to disable opcache.enable_cli for a while.
Applied a higher memory limit (512M), then enabled it back and it started working like a charm.

@realFlowControl
Copy link
Collaborator

Hey @JanTvrdik,
thanks for creating a reproducer in Docker. I tried to run this but could not reproduce, not on MacOS and not in your docker container. It could be that this is because I'm running on ARM64. Can you double check if you can still reproduce the issue?

@JanTvrdik
Copy link
Author

Yes. This is the ouput I get today:

OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
Segmentation fault
Command failed on iteration 20

@JanTvrdik
Copy link
Author

I also tried GitHub Codespaces, and it took a lot longer to fail, but eventually it did

https://codespaces.new/JanTvrdik/php-ext-parallel-segfault

Segmentation fault (core dumped)
Command failed on iteration 862

@hschimpf
Copy link

hschimpf commented Jul 9, 2024

I have a similar behavior, when running on PHP 8.0 all works flawlessly, but the same process on PHP version 8.1 and prior does segfault 1.

Tried changing some values on the PHP configuration (opcache, jit, buffer size, ...) but didn't found any solution.

Footnotes

  1. https://github.com/hschimpf/parallel-sdk/issues/26

@realFlowControl
Copy link
Collaborator

realFlowControl commented Oct 21, 2024

@JanTvrdik this seems fixed with #327 merged to develop. I'll try to draft a release this week

@cmb69
Copy link
Collaborator

cmb69 commented Nov 5, 2024

I'm not sure if I'm hitting this very issue, but I just noticed a couple of test failures with PHP 8.3 on Windows. These all seem to happen with bootstrap files, and only when OPcache JIT is enabled. The error message is VirtualProtect() failed [87] Falscher Parameter.

Stack backtrace
php_opcache.dll!zend_jit_unprotect() Line 4683 (c:\php-sdk\phpdev\vs16\x64\php-src-8.3\ext\opcache\jit\zend_jit.c:4683)
php_opcache.dll!zend_accel_script_persist(_zend_persistent_script * script, int for_shm) Line 1359 (c:\php-sdk\phpdev\vs16\x64\php-src-8.3\ext\opcache\zend_persist.c:1359)
php_opcache.dll!cache_script_in_shared_memory(_zend_persistent_script * new_persistent_script, _zend_string * key, bool * from_shared_memory) Line 1629 (c:\php-sdk\phpdev\vs16\x64\php-src-8.3\ext\opcache\ZendAccelerator.c:1629)
php_opcache.dll!persistent_compile_file(_zend_file_handle * file_handle, int type) Line 2156 (c:\php-sdk\phpdev\vs16\x64\php-src-8.3\ext\opcache\ZendAccelerator.c:2156)
[Inline Frame] php_parallel.dll!php_parallel_thread_bootstrap(_zend_string * file) Line 426 (c:\php-sdk\phpdev\vs16\x64\php-src-8.3\ext\parallel\src\scheduler.c:426)
php_parallel.dll!php_parallel_thread(void * arg) Line 459 (c:\php-sdk\phpdev\vs16\x64\php-src-8.3\ext\parallel\src\scheduler.c:459)
pthreadVC3.dll!__ptw32_threadStart() (Unbekannte Quelle:0)
ucrtbase.dll!00007ffbbac91bb2() (Unbekannte Quelle:0)
kernel32.dll!00007ffbbc3d7374() (Unbekannte Quelle:0)
ntdll.dll!00007ffbbce7cc91() (Unbekannte Quelle:0)

In zend_jit_unprotect(), dasm_buf is NULL, because for some reason zend_jit_startup() has not been called. Ah, that is because opcache.jit_buffer_size=0 by default. In this case JIT_G(on) is set to false, but apparently not for all threads created by ext/parallel. I think it is a bit contrived that you can enable JIT, but without an explicit jit_buffer_size it is not really enabled, but likely this can't be changed for BC reasons. Maybe just document that in case JIT is enabled, jit_buffer_size needs to be set to some reasonable value. With jit_buffer_size=64M, I don't get any test failures.

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

No branches or pull requests

5 participants