From 8fe1db208923f719f546f6bad95006ca8dee86cc Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Fri, 26 Aug 2022 16:08:06 +0200 Subject: [PATCH] Delay fiber VM stack cleanup until after observer has been called Signed-off-by: Bob Weinand --- Zend/zend_fibers.c | 25 ++++++++++++++++++++----- Zend/zend_fibers.h | 7 +++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 80a70d87f6f..0bb45d1c3dc 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -360,6 +360,10 @@ ZEND_API void zend_fiber_destroy_context(zend_fiber_context *context) { zend_observer_fiber_destroy_notify(context); + if (context->cleanup) { + context->cleanup(context); + } + zend_fiber_stack_free(context->stack); } @@ -441,6 +445,19 @@ ZEND_API void zend_fiber_switch_context(zend_fiber_transfer *transfer) } } +static void zend_fiber_cleanup(zend_fiber_context *context) +{ + zend_fiber *fiber = zend_fiber_from_context(context); + + zend_vm_stack current_stack = EG(vm_stack); + EG(vm_stack) = fiber->vm_stack; + zend_vm_stack_destroy(); + EG(vm_stack) = current_stack; + fiber->execute_data = NULL; + fiber->stack_bottom = NULL; + fiber->caller = NULL; +} + static ZEND_STACK_ALIGNED void zend_fiber_execute(zend_fiber_transfer *transfer) { ZEND_ASSERT(Z_TYPE(transfer->value) == IS_NULL && "Initial transfer value to fiber context must be NULL"); @@ -501,12 +518,10 @@ static ZEND_STACK_ALIGNED void zend_fiber_execute(zend_fiber_transfer *transfer) transfer->flags = ZEND_FIBER_TRANSFER_FLAG_BAILOUT; } zend_end_try(); - transfer->context = fiber->caller; + fiber->context.cleanup = &zend_fiber_cleanup; + fiber->vm_stack = EG(vm_stack); - zend_vm_stack_destroy(); - fiber->execute_data = NULL; - fiber->stack_bottom = NULL; - fiber->caller = NULL; + transfer->context = fiber->caller; } /* Handles forwarding of result / error from a transfer into the running fiber. */ diff --git a/Zend/zend_fibers.h b/Zend/zend_fibers.h index aefe2e53be6..2673e7814b0 100644 --- a/Zend/zend_fibers.h +++ b/Zend/zend_fibers.h @@ -71,6 +71,7 @@ typedef struct _zend_fiber_transfer { /* Coroutine functions must populate the given transfer with a new context * and (optional) data before they return. */ typedef void (*zend_fiber_coroutine)(zend_fiber_transfer *transfer); +typedef void (*zend_fiber_clean)(zend_fiber_context *context); struct _zend_fiber_context { /* Pointer to boost.context or ucontext_t data. */ @@ -82,6 +83,9 @@ struct _zend_fiber_context { /* Entrypoint function of the fiber. */ zend_fiber_coroutine function; + /* Cleanup function for fiber. */ + zend_fiber_clean cleanup; + /* Assigned C stack. */ zend_fiber_stack *stack; @@ -121,6 +125,9 @@ struct _zend_fiber { /* Frame on the bottom of the fiber vm stack. */ zend_execute_data *stack_bottom; + /* Active fiber vm stack. */ + zend_vm_stack vm_stack; + /* Storage for fiber return value. */ zval result; };