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_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(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_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(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_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_graceful_exit(void);
|
||||
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);
|
||||
EG(exception) = NULL;
|
||||
|
||||
zval graceful_exit;
|
||||
ZVAL_OBJ(&graceful_exit, zend_create_graceful_exit());
|
||||
|
||||
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) {
|
||||
EG(exception) = Z_OBJ(transfer.value);
|
||||
@ -659,13 +664,6 @@ ZEND_METHOD(Fiber, suspend)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user