1--TEST--
2Fibers in destructors 004: Suspend and throw in destructor
3--FILE--
4<?php
5
6register_shutdown_function(function () {
7    printf("Shutdown\n");
8});
9
10class Cycle {
11    public static $counter = 0;
12    public $self;
13    public function __construct() {
14        $this->self = $this;
15    }
16    public function __destruct() {
17        $id = self::$counter++;
18        printf("%d: Start destruct\n", $id);
19        if ($id === 0) {
20            global $f2;
21            $f2 = Fiber::getCurrent();
22            Fiber::suspend(new stdClass);
23        }
24        printf("%d: End destruct\n", $id);
25        throw new \Exception(sprintf("%d exception", $id));
26    }
27}
28
29$f = new Fiber(function () {
30    global $f2;
31    new Cycle();
32    new Cycle();
33    new Cycle();
34    try {
35        gc_collect_cycles();
36    } catch (\Exception $e) {
37        echo $e, "\n";
38    }
39    $f2->resume();
40});
41
42$f->start();
43
44?>
45--EXPECTF--
460: Start destruct
471: Start destruct
481: End destruct
492: Start destruct
502: End destruct
51Exception: 1 exception in %s:%d
52Stack trace:
53#0 [internal function]: Cycle->__destruct()
54#1 [internal function]: gc_destructor_fiber()
55#2 %s(%d): gc_collect_cycles()
56#3 [internal function]: {closure:%s:%d}()
57#4 %s(%d): Fiber->start()
58#5 {main}
59
60Next Exception: 2 exception in %s:%d
61Stack trace:
62#0 [internal function]: Cycle->__destruct()
63#1 [internal function]: gc_destructor_fiber()
64#2 %s(%d): gc_collect_cycles()
65#3 [internal function]: {closure:%s:%d}()
66#4 %s(%d): Fiber->start()
67#5 {main}
680: End destruct
69
70Fatal error: Uncaught Exception: 0 exception in %s:%d
71Stack trace:
72#0 [internal function]: Cycle->__destruct()
73#1 [internal function]: gc_destructor_fiber()
74#2 %s(%d): Fiber->resume()
75#3 [internal function]: {closure:%s:%d}()
76#4 %s(%d): Fiber->start()
77#5 {main}
78  thrown in %s on line %d
79Shutdown
80