From 779fe8e43a85f6fddb994dad6d2f4830062d1b4f Mon Sep 17 00:00:00 2001 From: Aaron Piotrowski Date: Wed, 5 May 2021 10:44:55 -0500 Subject: [PATCH] Check current_execute_data instead of flags in fiber destructor Checking EG(current_exectue_data) throws into the previous fiber instead of triggering a fatal error during shutdown. A fatal error is triggered only if the throwing destroyed fiber was resumed from {main}. --- ...tiple-destroyed-fibers-after-shutdown.phpt | 47 +++++++++++++++++++ Zend/zend_fibers.c | 2 +- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/fibers/throw-in-multiple-destroyed-fibers-after-shutdown.phpt diff --git a/Zend/tests/fibers/throw-in-multiple-destroyed-fibers-after-shutdown.phpt b/Zend/tests/fibers/throw-in-multiple-destroyed-fibers-after-shutdown.phpt new file mode 100644 index 00000000000..a85d36c3a6d --- /dev/null +++ b/Zend/tests/fibers/throw-in-multiple-destroyed-fibers-after-shutdown.phpt @@ -0,0 +1,47 @@ +--TEST-- +Throw in multiple destroyed fibers after shutdown +--FILE-- +start(); + + $fiber2 = new Fiber(function (): void { + try { + Fiber::suspend(); + } finally { + throw new Exception('test2'); + } + }); + + $fiber2->start(); + + Fiber::suspend(); +}); + +$fiber->start(); + +echo "done\n"; + +?> +--EXPECTF-- +done + +Fatal error: Uncaught Exception: test1 in %sthrow-in-multiple-destroyed-fibers-after-shutdown.php:%d +Stack trace: +#0 [internal function]: {closure}() +#1 {main} + +Next Exception: test2 in %sthrow-in-multiple-destroyed-fibers-after-shutdown.php:%d +Stack trace: +#0 [internal function]: {closure}() +#1 {main} + thrown in %sthrow-in-multiple-destroyed-fibers-after-shutdown.php on line %d diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 4c091c24633..54c72cd4a66 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -405,7 +405,7 @@ static void zend_fiber_object_destroy(zend_object *object) zend_exception_set_previous(EG(exception), exception); - if (EG(flags) & EG_FLAGS_IN_SHUTDOWN) { + if (!EG(current_execute_data)) { zend_exception_error(EG(exception), E_ERROR); } } else {