Delay fiber VM stack cleanup until after observer has been called

Signed-off-by: Bob Weinand <bobwei9@hotmail.com>
This commit is contained in:
Bob Weinand 2022-08-26 16:08:06 +02:00
parent 2f9bc6e37a
commit 8fe1db2089
2 changed files with 27 additions and 5 deletions

View File

@ -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. */

View File

@ -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;
};