krakjoe/uopz

Segfault in zend_mm_shutdown with php 7.4.8

pprkut opened this issue · 14 comments

I have uopz 6.1.2 installed and updated to php 7.4.8. Now every php command exits with a segmentation fault, with gdb revealing it happens in zend_mm_shutdown (no debug symbols here, so I doubt the backtrace would be very useful).

Disabled every other non-core extension I have installed, except ones coming with php directly, so no interference with xdebug or some such.

Dug deeper and it turns out, it does seem to be an interference with another extension after all. Tracked it down to having both uopz and opcache enabled. Disabling either of them makes the segfault go away.

cmb69 commented

I cannot reproduce segfaults with current PHP-7.4 head and uopz 6.1.2 on Windows with OPcache enabled. Are you using file_cache?

These are my opcache settings (as far as I can tell, they should be pretty much the default settings):

opcache.blacklist_filename => no value => no value
opcache.consistency_checks => 0 => 0
opcache.dups_fix => Off => Off
opcache.enable => On => On
opcache.enable_cli => Off => Off
opcache.enable_file_override => Off => Off
opcache.error_log => no value => no value
opcache.file_cache => no value => no value
opcache.file_cache_consistency_checks => On => On
opcache.file_cache_only => Off => Off
opcache.file_update_protection => 2 => 2
opcache.force_restart_timeout => 180 => 180
opcache.huge_code_pages => Off => Off
opcache.interned_strings_buffer => 8 => 8
opcache.lockfile_path => /tmp => /tmp
opcache.log_verbosity_level => 1 => 1
opcache.max_accelerated_files => 10000 => 10000
opcache.max_file_size => 0 => 0
opcache.max_wasted_percentage => 5 => 5
opcache.memory_consumption => 128 => 128
opcache.opt_debug_level => 0 => 0
opcache.optimization_level => 0x7FFE9FEE => 0x7FFE9FEE
opcache.preferred_memory_model => no value => no value
opcache.preload => no value => no value
opcache.preload_user => no value => no value
opcache.protect_memory => Off => Off
opcache.restrict_api => no value => no value
opcache.revalidate_freq => 2 => 2
opcache.revalidate_path => Off => Off
opcache.save_comments => On => On
opcache.use_cwd => On => On
opcache.validate_permission => Off => Off
opcache.validate_root => Off => Off
opcache.validate_timestamps => On => On

However, I am on linux though, so perhaps it's a platform specific thing?

Compiled a debug build of php and uopz and got this backtrace:

(gdb) run -r "var_dump(TRUE);"
Starting program: /usr/bin/php -r "var_dump(TRUE);"
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
bool(true)

Program received signal SIGSEGV, Segmentation fault.
0x000000000093c20a in zend_mm_shutdown (heap=0x7ffff6c00040, full=1, silent=1) at /tmp/php-7.4.8/Zend/zend_alloc.c:2255
2255                    zend_mm_chunk *q = p->next;
(gdb) bt
#0  0x000000000093c20a in zend_mm_shutdown (heap=0x7ffff6c00040, full=1, silent=1) at /tmp/php-7.4.8/Zend/zend_alloc.c:2255
#1  0x000000000093d786 in alloc_globals_dtor (alloc_globals=0x1838c90) at /tmp/php-7.4.8/Zend/zend_alloc.c:2772
#2  0x00000000008bfad4 in tsrm_shutdown () at /tmp/php-7.4.8/TSRM/TSRM.c:215
#3  0x0000000000a5fc88 in main (argc=3, argv=0x18379e0) at /tmp/php-7.4.8/sapi/cli/php_cli.c:1380
cmb69 commented

Okay, no file_cache, but a ZTS build. I checked only an NTS build so far.

cmb69 commented

I cannot reproduce with Windows ZTS either.

Also found that UOPZ June release and PHP 7.4.9 OPCACHE are incompatible, either ONE or the OTHER has to be disabled.
extension=uopz
zend_extension=php_opcache.dll

However, both work together fine up to 7.3.21.

Windows x64, IIS FastCGI.

I can easily reproduce it with an out-of-the-box WordPress 5.5 (latest version). Refresh the home page twice and it will instantly produced warnings about invalid class references, e.g.:

  1. Warning: register_shutdown_function(): Invalid shutdown callback 'WP_Fatal_Error_Handler::handle' passed in \wp-includes\error-protection.php on line 95
  2. Error: Call to undefined method wpdb::show_errors() in \wp-includes\wp-db.php on line 610

uopz.exit=1
[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=3907
opcache.revalidate_freq=30
opcache.enable_file_override=1
opcache.error_log = "C:\Logfiles\PHP\x64_OPcache_vXX.log"
opcache.log_verbosity_level=2
opcache.cache_id=PHP_XX
opcache.file_cache=C:\Windows\Temp\PHP\OpCache_vXX
opcache.file_update_protection=10

Naturally, can't tell if the fault lies with OpCache or with UOPZ.

cmb69 commented

I can confirm the behavior reported by @ASchmidt1. Running the built-in Webserver, and requesting the following script twice, gives Uncaught Error: Call to undefined method Foo::bar().

<?php

class Foo {
    public function bar() {}
}

(new Foo)->bar();

This happens on Windows as well as Linux for current PHP-7.4 with OPcache enabled and uopz 6.1.2.

I'm not sure, thought, whether this is related to the issue reported by @pprkut, since I still cannot reproduce a segfault.

cmb69 commented

See PR #130.

cmb69 commented

getting a log entry that stated that changing an immutable was not permitted

This is not directly related to the issue at hand, and is now documented. There is nothing that uopz could do to fix this, from what I can tell.

Thanks Christopher - and I hate to commit topic drift, since you are saying this is not related to the issue at hand. Should I start a new "issue" to host the "immutable" subject?

I read the documentation “the class entry of class or the function entry of function is immutable”, but to a PHP programmer (and that's all I am) that raises the all-important question: WHAT did I do to cause a class or method/function to become “immutable” vs. what do I need to do in my PHP code for it NOT to become an immutable “entry”.

I theory, functions themselves are always immutable, as in you cannot “change” a function in PHP?

But (at least to me) I don’t know what to make of the mention of an immutable “class entry”. I don’t believe we have an immutable declaration keyword for classes?

We have abstract classes that can’t be instantiated – but they can be extended into new child classes.
We have final classes that can be instantiated – but can NOT be used to derive child classes.
If PHP ever introduces an “immutable” keyword when declaring constants, then maybe any object instances could reject modification of any instance variables (properties)?

I only saw that log entry once in all my testing – I have no idea what triggered it, what I could have done to trigger it, and how I would have to adjust my PHP code to prevent ever triggering it?

cmb69 commented

@ASchmidt1, yes please open a new ticket for the "immutable" issue. :)

I don't intend to support versions below 8.