diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2020-11-18 12:46:12 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2020-11-18 12:46:12 +0100 |
commit | bbc0dd402aeb68a7b38b89ac75b987271caa6bc7 (patch) | |
tree | b13a804d809f63b3001135798ffaec52380100bc /Zend | |
parent | feed041fc88d14da20e3bb1db7e17b8982b2687f (diff) | |
parent | 99a8ec6e24d2788bb533ab5be8618a958adf24cf (diff) | |
download | php-git-bbc0dd402aeb68a7b38b89ac75b987271caa6bc7.tar.gz |
Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
Short-circuit get_gc for currently running generator
Diffstat (limited to 'Zend')
-rw-r--r-- | Zend/tests/generators/gc_running_generator.phpt | 25 | ||||
-rw-r--r-- | Zend/zend_generators.c | 10 |
2 files changed, 35 insertions, 0 deletions
diff --git a/Zend/tests/generators/gc_running_generator.phpt b/Zend/tests/generators/gc_running_generator.phpt new file mode 100644 index 0000000000..e702381b62 --- /dev/null +++ b/Zend/tests/generators/gc_running_generator.phpt @@ -0,0 +1,25 @@ +--TEST-- +GC on running generator +--FILE-- +<?php + +function gen() { + yield; + // Trigger GC while $v is being reassigned. + $ary = [new stdClass, new stdClass, new stdClass]; + $ary[0]->foo = $ary; + foreach ($ary as &$v) { } +} + +for ($i = 0; $i < 10000; $i++) { + // Make sure gen is registered as a GC root. + $gen = gen(); + $gen2 = $gen; + unset($gen); + foreach ($gen2 as $v) {} +} + +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 7746c3de9c..68c1865c00 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -324,6 +324,16 @@ static HashTable *zend_generator_get_gc(zend_object *object, zval **table, int * return NULL; } + if (generator->flags & ZEND_GENERATOR_CURRENTLY_RUNNING) { + /* If the generator is currently running, we certainly won't be able to GC any values it + * holds on to. The execute_data state might be inconsistent during execution (e.g. because + * GC has been triggered in the middle of a variable reassignment), so we should not try + * to inspect it here. */ + *table = NULL; + *n = 0; + return NULL; + } + op_array = &EX(func)->op_array; zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create(); |