7676#include "zend_types.h"
7777#include "zend_weakrefs.h"
7878#include "zend_string.h"
79+ #include "zend_exceptions.h"
7980
8081#ifndef GC_BENCH
8182# define GC_BENCH 0
@@ -1932,6 +1933,17 @@ static zend_fiber *gc_create_destructor_fiber(void)
19321933 return fiber ;
19331934}
19341935
1936+ static void remember_prev_exception (zend_object * * prev_exception )
1937+ {
1938+ if (EG (exception )) {
1939+ if (* prev_exception ) {
1940+ zend_exception_set_previous (EG (exception ), * prev_exception );
1941+ }
1942+ * prev_exception = EG (exception );
1943+ EG (exception ) = NULL ;
1944+ }
1945+ }
1946+
19351947static zend_never_inline void gc_call_destructors_in_fiber (uint32_t end )
19361948{
19371949 ZEND_ASSERT (!GC_G (dtor_fiber_running ));
@@ -1947,6 +1959,9 @@ static zend_never_inline void gc_call_destructors_in_fiber(uint32_t end)
19471959 zend_fiber_resume (fiber , NULL , NULL );
19481960 }
19491961
1962+ zend_object * exception = NULL ;
1963+ remember_prev_exception (& exception );
1964+
19501965 for (;;) {
19511966 /* At this point, fiber has executed until suspension */
19521967 GC_TRACE ("resumed from destructor fiber" );
@@ -1960,14 +1975,18 @@ static zend_never_inline void gc_call_destructors_in_fiber(uint32_t end)
19601975 /* We do not own the fiber anymore. It may be collected if the
19611976 * application does not reference it. */
19621977 zend_object_release (& fiber -> std );
1978+ remember_prev_exception (& exception );
19631979 fiber = gc_create_destructor_fiber ();
1980+ remember_prev_exception (& exception );
19641981 continue ;
19651982 } else {
19661983 /* Fiber suspended itself after calling all destructors */
19671984 GC_TRACE ("destructor fiber suspended itself" );
19681985 break ;
19691986 }
19701987 }
1988+
1989+ EG (exception ) = exception ;
19711990}
19721991
19731992/* Perform a garbage collection run. The default implementation of gc_collect_cycles. */
0 commit comments