From d093c10cafb86a7390b971c0fa0ee4ca88d5b3d2 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Wed, 2 Oct 2024 12:11:10 +0200 Subject: [PATCH] Fix reuse of dtor fiber during shutdown (#16026) --- Zend/tests/fibers/destructors_011.phpt | 70 ++++++++++++++++++++++++++ Zend/zend_gc.c | 3 ++ 2 files changed, 73 insertions(+) create mode 100644 Zend/tests/fibers/destructors_011.phpt diff --git a/Zend/tests/fibers/destructors_011.phpt b/Zend/tests/fibers/destructors_011.phpt new file mode 100644 index 00000000000..1cd9844e7c0 --- /dev/null +++ b/Zend/tests/fibers/destructors_011.phpt @@ -0,0 +1,70 @@ +--TEST-- +Fibers in destructors 011: gc collection after the dtor fiber is dtor +--FILE-- +self = $this; + } + public function __destruct() { + printf("%s\n", __METHOD__); + } +} + +class CreateGarbageInDtor { + public $self; + public function __construct() { + $this->self = $this; + } + public function __destruct() { + printf("%s\n", __METHOD__); + // Create an object whose dtor will be called after the dtor fiber's + new CollectCyclesInFiberInDtor(); + } +} + +class CollectCyclesInFiberInDtor { + public $self; + public function __construct() { + $this->self = $this; + } + public function __destruct() { + printf("%s\n", __METHOD__); + new SimpleCycle(); + print "Collecting cycles\n"; + $f = new Fiber(function () { + gc_collect_cycles(); + }); + $f->start(); + print "Done collecting cycles\n"; + } +} + +register_shutdown_function(function () { + print "Shutdown\n"; +}); + +// Create a cycle +new SimpleCycle(); + +// Collect cycles to create the dtor fiber +$f = new Fiber(function () { + gc_collect_cycles(); +}); +$f->start(); + +// Create an object whose dtor will be called during shutdown +// (by zend_objects_store_call_destructors) +new CreateGarbageInDtor(); + +?> +--EXPECT-- +SimpleCycle::__destruct +Shutdown +CreateGarbageInDtor::__destruct +CollectCyclesInFiberInDtor::__destruct +Collecting cycles +SimpleCycle::__destruct +Done collecting cycles diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c index 30314a1e48c..a966a106def 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -2261,6 +2261,9 @@ static ZEND_FUNCTION(gc_destructor_fiber) if (UNEXPECTED(fiber->flags & ZEND_FIBER_FLAG_DESTROYED)) { /* Fiber is being destroyed by shutdown sequence */ + if (GC_G(dtor_fiber) == fiber) { + GC_G(dtor_fiber) = NULL; + } GC_DELREF(&fiber->std); gc_check_possible_root((zend_refcounted*)&fiber->std.gc); return;