Commit: ab75ed6ba9b5eace710976bf76d631728d4bb403 Author: Nikita Popov <ni...@php.net> Sat, 23 Jun 2012 16:08:15 +0200 Parents: 14766e1417c721d9643f6a2a785db3e88b565814 Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=ab75ed6ba9b5eace710976bf76d631728d4bb403 Log: Disallow closing a generator during its execution If a generator is closed while it is running an E_WARNING is thrown and the call is ignored. Maybe a fatal error should be thrown instead? Changed paths: M Zend/zend_generators.c M Zend/zend_generators.h Diff: diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 487975e..bccbb48 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -300,6 +300,8 @@ static zend_object_value zend_generator_create(zend_class_entry *class_type TSRM /* The key will be incremented on first use, so it'll start at 0 */ generator->largest_used_integer_key = -1; + generator->is_currently_running = 0; + zend_object_std_init(&generator->std, class_type TSRMLS_CC); object.handle = zend_objects_store_put(generator, NULL, @@ -339,6 +341,8 @@ static void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */ zend_class_entry *original_scope = EG(scope); zend_class_entry *original_called_scope = EG(called_scope); + zend_bool original_is_currently_running = generator->is_currently_running; + /* Remember the current stack position so we can back up pushed args */ generator->original_stack_top = zend_vm_stack_top(TSRMLS_C); @@ -363,6 +367,8 @@ static void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */ EG(scope) = generator->execute_data->current_scope; EG(called_scope) = generator->execute_data->current_called_scope; + generator->is_currently_running = 1; + /* We want the backtrace to look as if the generator function was * called from whatever method we are current running (e.g. next()). * The first prev_execute_data contains an additional stack frame, @@ -387,6 +393,8 @@ static void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */ EG(scope) = original_scope; EG(called_scope) = original_called_scope; + generator->is_currently_running = original_is_currently_running; + /* The stack top before and after the execution differ, i.e. there are * arguments pushed to the stack. */ if (generator->original_stack_top != zend_vm_stack_top(TSRMLS_C)) { @@ -549,6 +557,11 @@ ZEND_METHOD(Generator, close) generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + if (generator->is_currently_running) { + zend_error(E_WARNING, "A generator cannot be closed while it is running"); + return; + } + zend_generator_close(generator, 0 TSRMLS_CC); } /* }}} */ diff --git a/Zend/zend_generators.h b/Zend/zend_generators.h index 89193bb..73d85287 100644 --- a/Zend/zend_generators.h +++ b/Zend/zend_generators.h @@ -46,6 +46,10 @@ typedef struct _zend_generator { temp_variable *send_target; /* Largest used integer key for auto-incrementing keys */ long largest_used_integer_key; + + /* We need to know whether the generator is currently executed to avoid it + * being closed while still running */ + zend_bool is_currently_running; } zend_generator; extern ZEND_API zend_class_entry *zend_ce_generator; -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php