[前][次][番号順一覧][スレッド一覧]

ruby-changes:67270

From: Peter <ko1@a...>
Date: Fri, 27 Aug 2021 23:13:48 +0900 (JST)
Subject: [ruby-changes:67270] ed31bdfeee (master): Fix memory leak in Variable Width Allocation

https://git.ruby-lang.org/ruby.git/commit/?id=ed31bdfeee

From ed31bdfeee3396bd703ba432630bc31933a08feb Mon Sep 17 00:00:00 2001
From: Peter Zhu <peter@p...>
Date: Fri, 27 Aug 2021 09:37:51 -0400
Subject: Fix memory leak in Variable Width Allocation

Force recycled objects could create a freelist for the page. At the
start of sweeping we should append to the freelist to avoid
permanently losing the slots on the freelist.
---
 gc.c | 50 +++++++++++++++++++++++++++-----------------------
 1 file changed, 27 insertions(+), 23 deletions(-)

diff --git a/gc.c b/gc.c
index f7ce094..7764daa 100644
--- a/gc.c
+++ b/gc.c
@@ -5535,6 +5535,30 @@ gc_mode_transition(rb_objspace_t *objspace, enum gc_mode mode) https://github.com/ruby/ruby/blob/trunk/gc.c#L5535
 }
 
 static void
+heap_page_freelist_append(struct heap_page *page, RVALUE *freelist)
+{
+    if (freelist) {
+        asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
+        if (page->freelist) {
+            RVALUE *p = page->freelist;
+            asan_unpoison_object((VALUE)p, false);
+            while (p->as.free.next) {
+                RVALUE *prev = p;
+                p = p->as.free.next;
+                asan_poison_object((VALUE)prev);
+                asan_unpoison_object((VALUE)p, false);
+            }
+            p->as.free.next = freelist;
+            asan_poison_object((VALUE)p);
+        }
+        else {
+            page->freelist = freelist;
+        }
+        asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
+    }
+}
+
+static void
 gc_sweep_start_heap(rb_objspace_t *objspace, rb_heap_t *heap)
 {
     heap->sweeping_page = list_top(&heap->pages, struct heap_page, page_node);
@@ -5560,12 +5584,10 @@ gc_sweep_start(rb_objspace_t *objspace) https://github.com/ruby/ruby/blob/trunk/gc.c#L5584
         rb_size_pool_t *size_pool = &size_pools[i];
 
 #if USE_RVARGC
-        if (size_pool->freelist) {
-            size_pool->using_page->freelist = (RVALUE *)size_pool->freelist;
-            size_pool->freelist = 0;
-        }
+        heap_page_freelist_append(size_pool->using_page, size_pool->freelist);
 
         size_pool->using_page = NULL;
+        size_pool->freelist = NULL;
 #endif
 
         gc_sweep_start_heap(objspace, SIZE_POOL_EDEN_HEAP(size_pool));
@@ -8713,25 +8735,7 @@ rb_gc_ractor_newobj_cache_clear(rb_ractor_newobj_cache_t *newobj_cache) https://github.com/ruby/ruby/blob/trunk/gc.c#L8735
     RVALUE *freelist = newobj_cache->freelist;
     RUBY_DEBUG_LOG("ractor using_page:%p freelist:%p", page, freelist);
 
-    if (page && freelist) {
-        asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
-        if (page->freelist) {
-            RVALUE *p = page->freelist;
-            asan_unpoison_object((VALUE)p, false);
-            while (p->as.free.next) {
-                RVALUE *prev = p;
-                p = p->as.free.next;
-                asan_poison_object((VALUE)prev);
-                asan_unpoison_object((VALUE)p, false);
-            }
-            p->as.free.next = freelist;
-            asan_poison_object((VALUE)p);
-        }
-        else {
-            page->freelist = freelist;
-        }
-        asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
-    }
+    heap_page_freelist_append(page, freelist);
 
     newobj_cache->using_page = NULL;
     newobj_cache->freelist = NULL;
-- 
cgit v1.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]