See PHI1277. Originally, see T13232#243866.
On MacOS with PHP 7.3.1 (and apparently other versions of 7.3.x), this script segfaults reliably:
<?php // Call "preg_match()" before we fork. preg_match('//', ''); // Now, fork. $pid = pcntl_fork(); if ($pid === -1) { die('Unable to fork.'); } // We're the parent, so wait for the child to exit. if ($pid) { $status = 0; pcntl_waitpid($pid, $status); printf("Child exited with status %d.\n", $status); exit(0); } // We're the child. Do nothing, we'll segfault on exit.
The backtrace looks like this on my system:
(lldb) bt * thread #1, stop reason = signal SIGSTOP * frame #0: 0x00000001074db459 php`sljit_free_code [inlined] sljit_free_exec(ptr=0x00000001087c3010) at sljitExecAllocator.c:260:28 [opt] frame #1: 0x00000001074db449 php`sljit_free_code(code=0x00000001087c3010) at sljitLir.c:501 [opt] frame #2: 0x00000001074db39d php`_pcre2_jit_free_8(executable_jit=0x00007ff127e8c640, memctl=0x00007ff127e8c500) at pcre2_jit_misc.c:92:5 [opt] frame #3: 0x00000001074b373f php`php_pcre2_code_free(code=0x00007ff127e8c500) at pcre2_compile.c:1189:5 [opt] frame #4: 0x000000010753f726 php`php_free_pcre_cache(data=<unavailable>) at php_pcre.c:148:2 [opt] frame #5: 0x00000001078e9129 php`zend_hash_destroy(ht=0x000000010819d560) at zend_hash.c:1428:6 [opt] frame #6: 0x000000010753b4b9 php`zm_globals_dtor_pcre(pcre_globals=<unavailable>) at php_pcre.c:275:2 [opt] frame #7: 0x00000001078ded76 php`module_destructor(module=0x00007ff127d0a420) at zend_API.c:2586:4 [opt] frame #8: 0x00000001078d63a1 php`module_destructor_zval(zv=<unavailable>) at zend.c:745:2 [opt] frame #9: 0x00000001078e9d38 php`zend_hash_graceful_reverse_destroy at zend_hash.c:1181:3 [opt] frame #10: 0x00000001078e9bb5 php`zend_hash_graceful_reverse_destroy [inlined] _zend_hash_del_el(ht=<unavailable>, idx=<unavailable>, p=<unavailable>) at zend_hash.c:1204 [opt] frame #11: 0x00000001078e9b72 php`zend_hash_graceful_reverse_destroy(ht=0x00000001081a2a98) at zend_hash.c:1658 [opt] frame #12: 0x00000001078d6484 php`zend_shutdown at zend.c:976:2 [opt] frame #13: 0x000000010786e03b php`php_module_shutdown at main.c:2489:2 [opt] frame #14: 0x00000001079986f6 php`main(argc=<unavailable>, argv=0x00007ffee8791a88) at php_cli.c:1404:3 [opt] frame #15: 0x00007fff6e41c3d5 libdyld.dylib`start + 1 frame #16: 0x00007fff6e41c3d5 libdyld.dylib`start + 1
Various tales from around the internet:
- https://github.com/Homebrew/homebrew-core/issues/35491
- https://github.com/vimeo/psalm/issues/1601
- https://github.com/bobthecow/psysh/issues/540
Setting pcre.jit = 0 works around this, and the setting can be changed at runtime, so that seems like a clear-cut way forward.