]> granicus.if.org Git - php/commitdiff
Fix generator being a cycle to itself
authorBob Weinand <bobwei9@hotmail.com>
Mon, 18 Apr 2016 21:54:41 +0000 (23:54 +0200)
committerBob Weinand <bobwei9@hotmail.com>
Mon, 18 Apr 2016 21:55:16 +0000 (23:55 +0200)
Zend/tests/generators/gc_with_yield_from.phpt [new file with mode: 0644]
Zend/zend_generators.c

diff --git a/Zend/tests/generators/gc_with_yield_from.phpt b/Zend/tests/generators/gc_with_yield_from.phpt
new file mode 100644 (file)
index 0000000..8c05561
--- /dev/null
@@ -0,0 +1,45 @@
+--TEST--
+Verify yield from on generators being properly cycle collected
+--FILE--
+<?php
+
+function root() {
+       global $gens; // create cyclic reference to root
+       try {
+               yield 1;
+       } finally {
+               var_dump($gens);
+       }
+}
+
+function gen($x) {
+       global $gens;
+       yield from $gens[] = $x ? gen(--$x) : root();
+}
+
+$gen = $gens[] = gen(2);
+var_dump($gen->current());
+unset($gen, $gens);
+print "collect\n";
+gc_collect_cycles();
+print "end\n";
+
+?>
+--EXPECT--
+int(1)
+collect
+array(4) {
+  [0]=>
+  object(Generator)#1 (0) {
+  }
+  [1]=>
+  object(Generator)#2 (0) {
+  }
+  [2]=>
+  object(Generator)#3 (0) {
+  }
+  [3]=>
+  object(Generator)#4 (0) {
+  }
+}
+end
index e2cc2382bd12b7ba3afb0b5c33f2624b7b31e3ce..33f187c96fca68e87892754e409564fb3365f117 100644 (file)
@@ -220,10 +220,10 @@ static uint32_t calc_gc_buffer_size(zend_generator *generator) /* {{{ */
 
                /* Yield from root references */
                if (generator->node.children == 0) {
-                       zend_generator *root = generator->node.ptr.root;
-                       while (root != generator) {
+                       zend_generator *child = generator, *root = generator->node.ptr.root;
+                       while (root != child) {
+                               child = child->node.parent;
                                size++;
-                               root = zend_generator_get_child(&root->node, generator);
                        }
                }
        }
@@ -287,8 +287,8 @@ static HashTable *zend_generator_get_gc(zval *object, zval **table, int *n) /* {
        if (generator->node.children == 0) {
                zend_generator *child = generator, *root = generator->node.ptr.root;
                while (root != child) {
-                       ZVAL_OBJ(gc_buffer++, &child->std);
                        child = child->node.parent;
+                       ZVAL_OBJ(gc_buffer++, &child->std);
                }
        }