]> granicus.if.org Git - php/commitdiff
Finally!!! Fixed segfault in GC
authorXinchen Hui <laruence@php.net>
Fri, 12 Sep 2014 17:52:47 +0000 (01:52 +0800)
committerXinchen Hui <laruence@php.net>
Fri, 12 Sep 2014 17:55:49 +0000 (01:55 +0800)
this must not be the final fix, but let's stop the segfault first and
use this to indicate where the problem is.

reproduced by phpspec

Zend/zend_gc.c
Zend/zend_gc.h

index adc02a3eb0b487834da1a38964c43dc07966a445..590b08a21485a3f6b27264109d28905d1ba02e2f 100644 (file)
@@ -492,8 +492,11 @@ tail_call:
                        } else if (GC_G(first_unused) != GC_G(last_unused)) {
                                buf = GC_G(first_unused);
                                GC_G(first_unused)++;
+                       } else {
+                               /* TODO: find a perfect way to handle such case */
+                               GC_G(gc_full) = 1;
                        }
-                       /* TODO: what should we do if we don't have room ??? */
+
                        if (buf) {
                                buf->ref = ref;
                                buf->next = GC_G(roots).next;
@@ -609,6 +612,18 @@ static int gc_collect_roots(TSRMLS_D)
                }
                current = current->next;
        }
+
+       if (GC_G(gc_full) == 1) {
+               current = GC_G(roots).next;
+               while (current != &GC_G(roots)) {
+                       GC_SET_ADDRESS(GC_INFO(current->ref), 0);
+                       GC_SET_BLACK(GC_INFO(current->ref));
+                       current = current->next;
+               }
+               gc_reset(TSRMLS_CC);
+               return 0;
+       }
+
        /* relink remaining roots into list to free */
        if (GC_G(roots).next != &GC_G(roots)) {
                if (GC_G(to_free).next == &GC_G(to_free)) {
index 84b7ef3208b794d921803edbf4b01fcb89ba637e..2eb8ea6ea30055c2e97b2aadc6cc9bfb5e896acc 100644 (file)
@@ -83,6 +83,7 @@ typedef struct _gc_root_buffer {
 typedef struct _zend_gc_globals {
        zend_bool         gc_enabled;
        zend_bool         gc_active;
+       zend_bool         gc_full;
 
        gc_root_buffer   *buf;                          /* preallocated arrays of buffers   */
        gc_root_buffer    roots;                        /* list of possible roots of cycles */