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

Reply via email to