зеркало из https://github.com/github/ruby.git
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.
This commit is contained in:
Родитель
3562c7ba33
Коммит
ed31bdfeee
50
gc.c
50
gc.c
|
@ -5534,6 +5534,30 @@ gc_mode_transition(rb_objspace_t *objspace, enum gc_mode mode)
|
||||||
gc_mode_set(objspace, mode);
|
gc_mode_set(objspace, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static void
|
||||||
gc_sweep_start_heap(rb_objspace_t *objspace, rb_heap_t *heap)
|
gc_sweep_start_heap(rb_objspace_t *objspace, rb_heap_t *heap)
|
||||||
{
|
{
|
||||||
|
@ -5560,12 +5584,10 @@ gc_sweep_start(rb_objspace_t *objspace)
|
||||||
rb_size_pool_t *size_pool = &size_pools[i];
|
rb_size_pool_t *size_pool = &size_pools[i];
|
||||||
|
|
||||||
#if USE_RVARGC
|
#if USE_RVARGC
|
||||||
if (size_pool->freelist) {
|
heap_page_freelist_append(size_pool->using_page, size_pool->freelist);
|
||||||
size_pool->using_page->freelist = (RVALUE *)size_pool->freelist;
|
|
||||||
size_pool->freelist = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_pool->using_page = NULL;
|
size_pool->using_page = NULL;
|
||||||
|
size_pool->freelist = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gc_sweep_start_heap(objspace, SIZE_POOL_EDEN_HEAP(size_pool));
|
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)
|
||||||
RVALUE *freelist = newobj_cache->freelist;
|
RVALUE *freelist = newobj_cache->freelist;
|
||||||
RUBY_DEBUG_LOG("ractor using_page:%p freelist:%p", page, freelist);
|
RUBY_DEBUG_LOG("ractor using_page:%p freelist:%p", page, freelist);
|
||||||
|
|
||||||
if (page && freelist) {
|
heap_page_freelist_append(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*));
|
|
||||||
}
|
|
||||||
|
|
||||||
newobj_cache->using_page = NULL;
|
newobj_cache->using_page = NULL;
|
||||||
newobj_cache->freelist = NULL;
|
newobj_cache->freelist = NULL;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче