diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 6a8ab80952b..0db3ad7e4f2 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -321,7 +321,7 @@ static void zend_fiber_switch_to(zend_fiber *fiber) zend_observer_fiber_switch_notify(fiber, previous); - if (UNEXPECTED(fiber->status == ZEND_FIBER_STATUS_BAILOUT)) { + if (UNEXPECTED(fiber->flags & ZEND_FIBER_FLAG_BAILOUT)) { // zend_bailout() was called in the fiber, so call it again in the previous fiber or {main}. zend_bailout(); } @@ -379,20 +379,20 @@ static void ZEND_STACK_ALIGNED zend_fiber_execute(zend_fiber_context *context) zval_ptr_dtor(&fiber->fci.function_name); if (EG(exception)) { - if (fiber->status == ZEND_FIBER_STATUS_SHUTDOWN) { + if (fiber->flags & ZEND_FIBER_FLAG_DESTROYED) { if (EXPECTED(zend_is_graceful_exit(EG(exception)) || zend_is_unwind_exit(EG(exception)))) { zend_clear_exception(); } } else { - fiber->status = ZEND_FIBER_STATUS_THREW; + fiber->flags = ZEND_FIBER_FLAG_THREW; } - } else { - fiber->status = ZEND_FIBER_STATUS_RETURNED; } } zend_catch { - fiber->status = ZEND_FIBER_STATUS_BAILOUT; + fiber->flags |= ZEND_FIBER_FLAG_BAILOUT; } zend_end_try(); + fiber->status = ZEND_FIBER_STATUS_DEAD; + zend_vm_stack_destroy(); fiber->execute_data = NULL; fiber->stack_bottom = NULL; @@ -422,7 +422,8 @@ static void zend_fiber_object_destroy(zend_object *object) zend_object *exception = EG(exception); EG(exception) = NULL; - fiber->status = ZEND_FIBER_STATUS_SHUTDOWN; + fiber->status = ZEND_FIBER_STATUS_RUNNING; + fiber->flags |= ZEND_FIBER_FLAG_DESTROYED; zend_fiber_switch_to(fiber); @@ -499,7 +500,7 @@ ZEND_API void zend_fiber_start(zend_fiber *fiber, zval *params, uint32_t param_c zend_fiber_switch_to(fiber); - if (fiber->status & ZEND_FIBER_STATUS_FINISHED) { + if (fiber->status == ZEND_FIBER_STATUS_DEAD) { RETURN_NULL(); } @@ -530,7 +531,7 @@ ZEND_API void zend_fiber_suspend(zval *value, zval *return_value) RETURN_THROWS(); } - if (UNEXPECTED(fiber->status == ZEND_FIBER_STATUS_SHUTDOWN)) { + if (UNEXPECTED(fiber->flags & ZEND_FIBER_FLAG_DESTROYED)) { zend_throw_error(zend_ce_fiber_error, "Cannot suspend in a force-closed fiber"); RETURN_THROWS(); } @@ -549,7 +550,7 @@ ZEND_API void zend_fiber_suspend(zval *value, zval *return_value) zend_fiber_suspend_from(fiber); - if (fiber->status == ZEND_FIBER_STATUS_SHUTDOWN) { + if (fiber->flags & ZEND_FIBER_FLAG_DESTROYED) { // This occurs when the fiber is GC'ed while suspended. zend_throw_graceful_exit(); RETURN_THROWS(); @@ -599,7 +600,7 @@ ZEND_API void zend_fiber_resume(zend_fiber *fiber, zval *value, zval *return_val zend_fiber_switch_to(fiber); - if (fiber->status & ZEND_FIBER_STATUS_FINISHED) { + if (fiber->status == ZEND_FIBER_STATUS_DEAD) { RETURN_NULL(); } @@ -637,7 +638,7 @@ ZEND_API void zend_fiber_throw(zend_fiber *fiber, zval *exception, zval *return_ zend_fiber_switch_to(fiber); - if (fiber->status & ZEND_FIBER_STATUS_FINISHED) { + if (fiber->status == ZEND_FIBER_STATUS_DEAD) { RETURN_NULL(); } @@ -700,7 +701,7 @@ ZEND_METHOD(Fiber, isTerminated) fiber = (zend_fiber *) Z_OBJ_P(getThis()); - RETURN_BOOL(fiber->status & ZEND_FIBER_STATUS_FINISHED); + RETURN_BOOL(fiber->status == ZEND_FIBER_STATUS_DEAD); } ZEND_METHOD(Fiber, getReturn) @@ -711,13 +712,15 @@ ZEND_METHOD(Fiber, getReturn) fiber = (zend_fiber *) Z_OBJ_P(getThis()); - if (fiber->status != ZEND_FIBER_STATUS_RETURNED) { + if (fiber->status != ZEND_FIBER_STATUS_DEAD || fiber->flags) { const char *message; if (fiber->status == ZEND_FIBER_STATUS_INIT) { message = "The fiber has not been started"; - } else if (fiber->status == ZEND_FIBER_STATUS_THREW) { + } else if (fiber->flags & ZEND_FIBER_FLAG_THREW) { message = "The fiber threw an exception"; + } else if (fiber->flags & ZEND_FIBER_FLAG_BAILOUT) { + message = "The fiber exited with a fatal error"; } else { message = "The fiber has not returned"; } diff --git a/Zend/zend_fibers.h b/Zend/zend_fibers.h index d1a083baf18..b26e22e9a88 100644 --- a/Zend/zend_fibers.h +++ b/Zend/zend_fibers.h @@ -25,6 +25,19 @@ BEGIN_EXTERN_C() +typedef enum { + ZEND_FIBER_STATUS_INIT, + ZEND_FIBER_STATUS_RUNNING, + ZEND_FIBER_STATUS_SUSPENDED, + ZEND_FIBER_STATUS_DEAD, +} zend_fiber_status; + +typedef enum { + ZEND_FIBER_FLAG_THREW = 1 << 0, + ZEND_FIBER_FLAG_BAILOUT = 1 << 1, + ZEND_FIBER_FLAG_DESTROYED = 1 << 2, +} zend_fiber_flag; + void zend_register_fiber_ce(void); void zend_fiber_init(void); @@ -59,8 +72,11 @@ typedef struct _zend_fiber { /* Fiber PHP object handle. */ zend_object std; - /* Status of the fiber, one of the ZEND_FIBER_STATUS_* constants. */ - zend_uchar status; + /* Status of the fiber, one of the zend_fiber_status values. */ + zend_fiber_status status; + + /* Flags of the fiber, bit field of the zend_fiber_flag values. */ + zend_uchar flags; /* Callback and info / cache to be used when fiber is started. */ zend_fcall_info fci; @@ -82,16 +98,6 @@ typedef struct _zend_fiber { zval value; } zend_fiber; -static const zend_uchar ZEND_FIBER_STATUS_INIT = 0x0; -static const zend_uchar ZEND_FIBER_STATUS_SUSPENDED = 0x1; -static const zend_uchar ZEND_FIBER_STATUS_RUNNING = 0x2; -static const zend_uchar ZEND_FIBER_STATUS_RETURNED = 0x4; -static const zend_uchar ZEND_FIBER_STATUS_THREW = 0x8; -static const zend_uchar ZEND_FIBER_STATUS_SHUTDOWN = 0x10; -static const zend_uchar ZEND_FIBER_STATUS_BAILOUT = 0x20; - -static const zend_uchar ZEND_FIBER_STATUS_FINISHED = 0x2c; - /* These functions create and manipulate a Fiber object, allowing any internal function to start, resume, or suspend a fiber. */ ZEND_API zend_fiber *zend_fiber_create(const zend_fcall_info *fci, const zend_fcall_info_cache *fci_cache); ZEND_API void zend_fiber_start(zend_fiber *fiber, zval *params, uint32_t param_count, zend_array *named_params, zval *return_value); diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 379fde06b63..56e00800d42 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -6873,7 +6873,7 @@ ZEND_METHOD(ReflectionFiber, getFiber) } #define REFLECTION_CHECK_VALID_FIBER(fiber) do { \ - if (fiber == NULL || fiber->status == ZEND_FIBER_STATUS_INIT || fiber->status & ZEND_FIBER_STATUS_FINISHED) { \ + if (fiber == NULL || fiber->status == ZEND_FIBER_STATUS_INIT || fiber->status == ZEND_FIBER_STATUS_DEAD) { \ zend_throw_error(NULL, "Cannot fetch information from a fiber that has not been started or is terminated"); \ RETURN_THROWS(); \ } \ @@ -6948,7 +6948,7 @@ ZEND_METHOD(ReflectionFiber, getCallable) ZEND_PARSE_PARAMETERS_NONE(); - if (fiber == NULL || fiber->status & ZEND_FIBER_STATUS_FINISHED) { + if (fiber == NULL || fiber->status == ZEND_FIBER_STATUS_DEAD) { zend_throw_error(NULL, "Cannot fetch the callable from a fiber that has terminated"); \ RETURN_THROWS(); } diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 54e70a9ab25..7422f25bbb3 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -425,9 +425,11 @@ static void fiber_enter_observer(zend_fiber *from, zend_fiber *to) if (to->status == ZEND_FIBER_STATUS_INIT) { php_printf("\n", to); } else if (to->status == ZEND_FIBER_STATUS_RUNNING && (!from || from->status == ZEND_FIBER_STATUS_RUNNING)) { - php_printf("\n", to); - } else if (to->status == ZEND_FIBER_STATUS_SHUTDOWN) { - php_printf("\n", to); + if (to->flags & ZEND_FIBER_FLAG_DESTROYED) { + php_printf("\n", to); + } else if (to->status != ZEND_FIBER_STATUS_DEAD) { + php_printf("\n", to); + } } } } @@ -439,12 +441,14 @@ static void fiber_suspend_observer(zend_fiber *from, zend_fiber *to) if (from) { if (from->status == ZEND_FIBER_STATUS_SUSPENDED) { php_printf("\n", from); - } else if (from->status == ZEND_FIBER_STATUS_RETURNED) { - php_printf("\n", from); - } else if (from->status == ZEND_FIBER_STATUS_THREW) { - php_printf("\n", from); - } else if (from->status == ZEND_FIBER_STATUS_SHUTDOWN) { - php_printf("\n", from); + } else if (from->status == ZEND_FIBER_STATUS_DEAD) { + if (from->flags & ZEND_FIBER_FLAG_THREW) { + php_printf("\n", from); + } else if (from->flags & ZEND_FIBER_FLAG_DESTROYED) { + php_printf("\n", from); + } else { + php_printf("\n", from); + } } } } diff --git a/ext/zend_test/tests/observer_fiber_05.phpt b/ext/zend_test/tests/observer_fiber_05.phpt index 574efb36aff..9cb0ab0254f 100644 --- a/ext/zend_test/tests/observer_fiber_05.phpt +++ b/ext/zend_test/tests/observer_fiber_05.phpt @@ -44,9 +44,7 @@ $fiber->resume(); - -