1--TEST-- 2Fibers in destructors 005: Suspended and not resumed destructor 3--FILE-- 4<?php 5 6register_shutdown_function(function () { 7 printf("Shutdown\n"); 8}); 9 10class Cycle { 11 public $self; 12 public function __construct(public int $id) { 13 $this->self = $this; 14 } 15 public function __destruct() { 16 printf("%d: Start destruct\n", $this->id); 17 try { 18 if ($this->id === 0) { 19 /* Fiber will be collected by GC because it's not referenced */ 20 Fiber::suspend(new stdClass); 21 } else if ($this->id === 1) { 22 /* Fiber will be dtor during shutdown */ 23 global $f2; 24 $f2 = Fiber::getCurrent(); 25 Fiber::suspend(new stdClass); 26 } 27 } finally { 28 printf("%d: End destruct\n", $this->id); 29 } 30 } 31} 32 33$refs = []; 34$f = new Fiber(function () use (&$refs) { 35 $refs[] = WeakReference::create(new Cycle(0)); 36 $refs[] = WeakReference::create(new Cycle(1)); 37 $refs[] = WeakReference::create(new Cycle(2)); 38 gc_collect_cycles(); 39}); 40 41$f->start(); 42 43gc_collect_cycles(); 44 45foreach ($refs as $id => $ref) { 46 printf("%d: %s\n", $id, $ref->get() ? 'Live' : 'Collected'); 47} 48 49?> 50--EXPECT-- 512: Start destruct 522: End destruct 530: Start destruct 540: End destruct 551: Start destruct 560: Collected 571: Live 582: Collected 59Shutdown 601: End destruct 61