summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2014-04-14 22:41:42 +0400
committerDmitry Stogov <dmitry@zend.com>2014-04-14 22:41:42 +0400
commitb0b54e8db4d67dba3dec1bc1651f351d4762f984 (patch)
tree671b44d52a5d2fda6eaded109b5c415f6012f5cb
parent703c1bc570d1fc9a379fa38b298d6759a4b1a687 (diff)
downloadphp-git-b0b54e8db4d67dba3dec1bc1651f351d4762f984.tar.gz
Fixed nested GC calls (valgrind error in Zend/tests/gc_016.phpt)
-rw-r--r--Zend/zend_gc.c30
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) {