Skip to content

Fix GH-19983: GC assertion failure with fibers, generators and destructors#21527

Closed
iliaal wants to merge 4514 commits intophp:PHP-8.4from
iliaal:fix/gh-19983-gc-dtor-fiber-exception
Closed

Fix GH-19983: GC assertion failure with fibers, generators and destructors#21527
iliaal wants to merge 4514 commits intophp:PHP-8.4from
iliaal:fix/gh-19983-gc-dtor-fiber-exception

Conversation

@iliaal
Copy link
Copy Markdown
Contributor

@iliaal iliaal commented Mar 25, 2026

When GC runs inside a fiber handling an exception (e.g. during zend_fiber_object_destroy), EG(exception) is set. gc_call_destructors_in_fiber() saved and cleared the exception after creating the destructor fiber. Since zend_call_function() returns early when EG(exception) is set, the destructor fiber's handler never ran, leaving DTOR_GARBAGE entries in the root buffer. On the next GC cycle, gc_collect_roots() hit an alignment assertion on these stale entries.

Move remember_prev_exception() before the destructor fiber creation/resume so EG(exception) is cleared before zend_call_function() runs inside the fiber.

Fixes #19983

iluuu1994 and others added 30 commits February 24, 2026 02:15
* PHP-8.4:
  Fix benchmarking head sha
  Fix ccache for alpine and msan
  Fix coverage label job selection
  Fix ccache for coverage and pecl builds
* PHP-8.5:
  Fix benchmarking head sha
  Fix ccache for alpine and msan
  Fix coverage label job selection
  Fix ccache for coverage and pecl builds
* PHP-8.5:
  Update IR (php#21288)
* PHP-8.5:
  PHP-8.5 is now for PHP 8.5.5-dev
* PHP-8.4:
  Fix preloaded constant erroneously propagated to file-cached script
* PHP-8.5:
  Fix preloaded constant erroneously propagated to file-cached script
* PHP-8.5:
  Fix missed php_version changes
* PHP-8.4:
  ext/pcre: preg_match() fix memory leak with invalid regexes.
* PHP-8.5:
  ext/pcre: preg_match() fix memory leak with invalid regexes.
* PHP-8.4:
  php_version.h: remove trailing whitespace
* PHP-8.5:
  php_version.h: remove trailing whitespace
* PHP-8.5:
  Update IR
… error (php#21260)

When a PCRE execution error occurs (e.g. malformed UTF-8 with /u
modifier), preg_grep() was returning a partial result array containing
only the entries processed before the error. All other preg_* functions
return false on execution errors.

After the match loop, check PCRE_G(error_code) and if an error
occurred, destroy the partial array and return false instead.

Fixes phpGH-11936
Instead of hardcoding the file extensions for shared PHP extensions
(which in most cases are '.so', or '.dll'), this uses file extension for
the current PHP build as it was defined during the configure/build
phase. There can be systems where some other file extension is used for
shared modules.
internal refactorings:

- pcntl_signal_get_handler() max signals handling simplification,
 reusing the num_signals global.
- pcntl_alarm() accepts a zend_long (signed) but passes it to alarm(),
which takes an unsigned int. Negative values silently wrap to large
unsigned values, scheduling an alarm far in the future instead of
raising an error. Also reject large values above unsigned long
max value.

close phpGH-21282
* PHP-8.4:
  ext/pcre: fix memory leaks on error paths
* PHP-8.5:
  ext/pcre: fix memory leaks on error paths
* PHP-8.5:
  ext/pcre: fix new pcre2 test
Add support for new functions present in recent libsodium versions:

- Functions for IP address encryption:
  - sodium_crypto_ipcrypt_*
  - sodium_bin2ip/sodium_ip2bin helpers

- Extendable output functions:
  - SHAKE128/SHAKE256
  - TurboSHAKE128/TurboSHAKE256
* PHP-8.4:
  [CI][skip ci] Fix benchmarking summary
* PHP-8.5:
  [CI][skip ci] Fix benchmarking summary
Girgias and others added 15 commits March 24, 2026 17:46
* PHP-8.4:
  PHP-8.4 is now for PHP 8.4.21-dev
* PHP-8.5:
  PHP-8.4 is now for PHP 8.4.21-dev
…tructors

When GC runs inside a fiber handling an exception (e.g. during
zend_fiber_object_destroy), EG(exception) is set.
gc_call_destructors_in_fiber() saved and cleared the exception after
creating the destructor fiber. Since zend_call_function() returns early
when EG(exception) is set, the destructor fiber's handler never ran,
leaving DTOR_GARBAGE entries in the root buffer. On the next GC cycle,
gc_collect_roots() hit an alignment assertion on these stale entries.

Move remember_prev_exception() before the destructor fiber
creation/resume so EG(exception) is cleared before zend_call_function()
runs inside the fiber.

Closes phpGH-19983
Copy link
Copy Markdown
Member

@arnaud-lb arnaud-lb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! This looks good to me.

Could you rebase on PHP-8.4?

@iliaal iliaal changed the base branch from master to PHP-8.4 March 25, 2026 16:21
@iliaal iliaal closed this Mar 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GC Assertion Failure: Unaligned Reference Pointer in gc_collect_roots()