From 46bd055c0aaa82ebb1b2b68d491da791bd34c24c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=9A=93?= Date: Mon, 21 Apr 2025 11:16:21 -0400 Subject: [PATCH] Fix memory leak in `cont_restore_thread` in Ruby in libretro builds --- libretro/ruby-jump-buffer.patch | 54 +++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/libretro/ruby-jump-buffer.patch b/libretro/ruby-jump-buffer.patch index c80f2222..26bd3bb4 100644 --- a/libretro/ruby-jump-buffer.patch +++ b/libretro/ruby-jump-buffer.patch @@ -1,5 +1,59 @@ # Fixes a memory leak in WASI builds of Ruby where VM jump buffers are sometimes not freed. +--- a/cont.c ++++ b/cont.c +@@ -1518,6 +1518,51 @@ cont_restore_thread(rb_context_t *cont) + rb_raise(rb_eRuntimeError, "can't call across trace_func"); + } + ++#if defined(__wasm__) && !defined(__EMSCRIPTEN__) ++ if (th->ec->tag != sec->tag) { ++ /* find the lowest common ancestor tag of the current EC and the saved EC */ ++ ++ struct rb_vm_tag *lowest_common_ancestor = NULL; ++ size_t num_tags = 0; ++ size_t num_saved_tags = 0; ++ for (struct rb_vm_tag *tag = th->ec->tag; tag != NULL; tag = tag->prev) { ++ ++num_tags; ++ } ++ for (struct rb_vm_tag *tag = sec->tag; tag != NULL; tag = tag->prev) { ++ ++num_saved_tags; ++ } ++ ++ size_t min_tags = num_tags <= num_saved_tags ? num_tags : num_saved_tags; ++ ++ struct rb_vm_tag *tag = th->ec->tag; ++ while (num_tags > min_tags) { ++ tag = tag->prev; ++ --num_tags; ++ } ++ ++ struct rb_vm_tag *saved_tag = sec->tag; ++ while (num_saved_tags > min_tags) { ++ saved_tag = saved_tag->prev; ++ --num_saved_tags; ++ } ++ ++ while (min_tags > 0) { ++ if (tag == saved_tag) { ++ lowest_common_ancestor = tag; ++ break; ++ } ++ tag = tag->prev; ++ saved_tag = saved_tag->prev; ++ --min_tags; ++ } ++ ++ /* free all the jump buffers between the current EC's tag and the lowest common ancestor tag */ ++ for (struct rb_vm_tag *tag = th->ec->tag; tag != lowest_common_ancestor; tag = tag->prev) { ++ rb_vm_tag_jmpbuf_deinit(&tag->buf); ++ } ++ } ++#endif ++ + /* copy vm stack */ + #ifdef CAPTURE_JUST_VALID_VM_STACK + MEMCPY(th->ec->vm_stack, --- a/signal.c +++ b/signal.c @@ -849,6 +849,7 @@ check_stack_overflow(int sig, const uintptr_t addr, const ucontext_t *ctx)