diff options
author | Dmitry Stogov <dmitry@zend.com> | 2014-04-14 22:41:42 +0400 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2014-04-14 22:41:42 +0400 |
commit | b0b54e8db4d67dba3dec1bc1651f351d4762f984 (patch) | |
tree | 671b44d52a5d2fda6eaded109b5c415f6012f5cb | |
parent | 703c1bc570d1fc9a379fa38b298d6759a4b1a687 (diff) | |
download | php-git-b0b54e8db4d67dba3dec1bc1651f351d4762f984.tar.gz |
Fixed nested GC calls (valgrind error in Zend/tests/gc_016.phpt)
-rw-r--r-- | Zend/zend_gc.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c index ec72d1e5ce..ea33122240 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -612,6 +612,7 @@ ZEND_API int gc_collect_cycles(TSRMLS_D) if (GC_G(roots).next != &GC_G(roots)) { gc_root_buffer *current, *orig_next_to_free; zend_refcounted *p; + gc_root_buffer to_free; if (GC_G(gc_active)) { return 0; @@ -621,13 +622,28 @@ ZEND_API int gc_collect_cycles(TSRMLS_D) gc_mark_roots(TSRMLS_C); gc_scan_roots(TSRMLS_C); count = gc_collect_roots(TSRMLS_C); + GC_G(gc_active) = 0; + + if (GC_G(to_free).next == &GC_G(to_free)) { + /* nothing to free */ + return 0; + } + + /* Copy global to_free list into local list */ + to_free.next = GC_G(to_free).next; + to_free.prev = GC_G(to_free).prev; + to_free.next->prev = &to_free; + to_free.prev->next = &to_free; + + /* Free global list */ + GC_G(to_free).next = &GC_G(to_free); + GC_G(to_free).prev = &GC_G(to_free); orig_next_to_free = GC_G(next_to_free); - GC_G(gc_active) = 0; /* First call destructors */ - current = GC_G(to_free).next; - while (current != &GC_G(to_free)) { + current = to_free.next; + while (current != &to_free) { p = current->ref; GC_G(next_to_free) = current->next; if (GC_TYPE(p) == IS_OBJECT) { @@ -649,8 +665,8 @@ ZEND_API int gc_collect_cycles(TSRMLS_D) } /* Destroy zvals */ - current = GC_G(to_free).next; - while (current != &GC_G(to_free)) { + current = to_free.next; + while (current != &to_free) { p = current->ref; GC_G(next_to_free) = current->next; if (GC_TYPE(p) == IS_OBJECT) { @@ -677,8 +693,8 @@ ZEND_API int gc_collect_cycles(TSRMLS_D) } /* Free objects */ - current = GC_G(to_free).next; - while (current != &GC_G(to_free)) { + current = to_free.next; + while (current != &to_free) { p = current->ref; GC_G(next_to_free) = current->next; if (GC_TYPE(p) == IS_OBJECT) { |