mirror of
https://github.com/php/php-src.git
synced 2024-09-21 09:57:23 +00:00
Allow creating Graceful/UnwindExit and use when destroying a fiber (#7174)
Direct creation of GracefulExit allows the the special exception object to be transfered and thrown into a destroyed fiber using the same path as any other exception thrown into a fiber instead of needing to check for a flag.
This commit is contained in:
parent
773e9ba5d6
commit
66442a51d1
@ -1002,10 +1002,20 @@ ZEND_API ZEND_COLD void zend_throw_exception_object(zval *exception) /* {{{ */
|
|||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
ZEND_API ZEND_COLD zend_object *zend_create_unwind_exit(void)
|
||||||
|
{
|
||||||
|
return zend_objects_new(&zend_ce_unwind_exit);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZEND_API ZEND_COLD zend_object *zend_create_graceful_exit(void)
|
||||||
|
{
|
||||||
|
return zend_objects_new(&zend_ce_graceful_exit);
|
||||||
|
}
|
||||||
|
|
||||||
ZEND_API ZEND_COLD void zend_throw_unwind_exit(void)
|
ZEND_API ZEND_COLD void zend_throw_unwind_exit(void)
|
||||||
{
|
{
|
||||||
ZEND_ASSERT(!EG(exception));
|
ZEND_ASSERT(!EG(exception));
|
||||||
EG(exception) = zend_objects_new(&zend_ce_unwind_exit);
|
EG(exception) = zend_create_unwind_exit();
|
||||||
EG(opline_before_exception) = EG(current_execute_data)->opline;
|
EG(opline_before_exception) = EG(current_execute_data)->opline;
|
||||||
EG(current_execute_data)->opline = EG(exception_op);
|
EG(current_execute_data)->opline = EG(exception_op);
|
||||||
}
|
}
|
||||||
@ -1013,7 +1023,7 @@ ZEND_API ZEND_COLD void zend_throw_unwind_exit(void)
|
|||||||
ZEND_API ZEND_COLD void zend_throw_graceful_exit(void)
|
ZEND_API ZEND_COLD void zend_throw_graceful_exit(void)
|
||||||
{
|
{
|
||||||
ZEND_ASSERT(!EG(exception));
|
ZEND_ASSERT(!EG(exception));
|
||||||
EG(exception) = zend_objects_new(&zend_ce_graceful_exit);
|
EG(exception) = zend_create_graceful_exit();
|
||||||
EG(opline_before_exception) = EG(current_execute_data)->opline;
|
EG(opline_before_exception) = EG(current_execute_data)->opline;
|
||||||
EG(current_execute_data)->opline = EG(exception_op);
|
EG(current_execute_data)->opline = EG(exception_op);
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,8 @@ ZEND_API ZEND_COLD zend_result zend_exception_error(zend_object *exception, int
|
|||||||
ZEND_NORETURN void zend_exception_uncaught_error(const char *prefix, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2);
|
ZEND_NORETURN void zend_exception_uncaught_error(const char *prefix, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2);
|
||||||
ZEND_API zend_string *zend_trace_to_string(HashTable *trace, bool include_main);
|
ZEND_API zend_string *zend_trace_to_string(HashTable *trace, bool include_main);
|
||||||
|
|
||||||
|
ZEND_API ZEND_COLD zend_object *zend_create_unwind_exit(void);
|
||||||
|
ZEND_API ZEND_COLD zend_object *zend_create_graceful_exit(void);
|
||||||
ZEND_API ZEND_COLD void zend_throw_unwind_exit(void);
|
ZEND_API ZEND_COLD void zend_throw_unwind_exit(void);
|
||||||
ZEND_API ZEND_COLD void zend_throw_graceful_exit(void);
|
ZEND_API ZEND_COLD void zend_throw_graceful_exit(void);
|
||||||
ZEND_API bool zend_is_unwind_exit(const zend_object *ex);
|
ZEND_API bool zend_is_unwind_exit(const zend_object *ex);
|
||||||
|
@ -539,9 +539,14 @@ static void zend_fiber_object_destroy(zend_object *object)
|
|||||||
zend_object *exception = EG(exception);
|
zend_object *exception = EG(exception);
|
||||||
EG(exception) = NULL;
|
EG(exception) = NULL;
|
||||||
|
|
||||||
|
zval graceful_exit;
|
||||||
|
ZVAL_OBJ(&graceful_exit, zend_create_graceful_exit());
|
||||||
|
|
||||||
fiber->flags |= ZEND_FIBER_FLAG_DESTROYED;
|
fiber->flags |= ZEND_FIBER_FLAG_DESTROYED;
|
||||||
|
|
||||||
zend_fiber_transfer transfer = zend_fiber_resume(fiber, NULL, false);
|
zend_fiber_transfer transfer = zend_fiber_resume(fiber, &graceful_exit, true);
|
||||||
|
|
||||||
|
zval_ptr_dtor(&graceful_exit);
|
||||||
|
|
||||||
if (transfer.flags & ZEND_FIBER_TRANSFER_FLAG_ERROR) {
|
if (transfer.flags & ZEND_FIBER_TRANSFER_FLAG_ERROR) {
|
||||||
EG(exception) = Z_OBJ(transfer.value);
|
EG(exception) = Z_OBJ(transfer.value);
|
||||||
@ -659,13 +664,6 @@ ZEND_METHOD(Fiber, suspend)
|
|||||||
|
|
||||||
zend_fiber_transfer transfer = zend_fiber_suspend(fiber, value);
|
zend_fiber_transfer transfer = zend_fiber_suspend(fiber, value);
|
||||||
|
|
||||||
if (fiber->flags & ZEND_FIBER_FLAG_DESTROYED) {
|
|
||||||
// This occurs when the fiber is GC'ed while suspended.
|
|
||||||
zval_ptr_dtor(&transfer.value);
|
|
||||||
zend_throw_graceful_exit();
|
|
||||||
RETURN_THROWS();
|
|
||||||
}
|
|
||||||
|
|
||||||
zend_fiber_delegate_transfer_result(&transfer, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
zend_fiber_delegate_transfer_result(&transfer, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user