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/