diff --git a/ruby/ext/google/protobuf_c/defs.c b/ruby/ext/google/protobuf_c/defs.c index aaa8b4dc7af0..3bd18e840028 100644 --- a/ruby/ext/google/protobuf_c/defs.c +++ b/ruby/ext/google/protobuf_c/defs.c @@ -159,6 +159,7 @@ VALUE DescriptorPool_add_serialized_file(VALUE _self, rb_raise(cTypeError, "Unable to build file to DescriptorPool: %s", upb_Status_ErrorMessage(&status)); } + RB_GC_GUARD(arena_rb); return get_filedef_obj(_self, filedef); } diff --git a/ruby/ext/google/protobuf_c/protobuf.c b/ruby/ext/google/protobuf_c/protobuf.c index 4d3e1a51448e..2135cca462c9 100644 --- a/ruby/ext/google/protobuf_c/protobuf.c +++ b/ruby/ext/google/protobuf_c/protobuf.c @@ -193,9 +193,20 @@ const rb_data_type_t Arena_type = { .flags = RUBY_TYPED_FREE_IMMEDIATELY, }; +static void* ruby_upb_allocfunc(upb_alloc* alloc, void* ptr, size_t oldsize, size_t size) { + if (size == 0) { + xfree(ptr); + return NULL; + } else { + return xrealloc(ptr, size); + } +} + +upb_alloc ruby_upb_alloc = {&ruby_upb_allocfunc}; + static VALUE Arena_alloc(VALUE klass) { Arena *arena = ALLOC(Arena); - arena->arena = upb_Arena_New(); + arena->arena = upb_Arena_Init(NULL, 0, &ruby_upb_alloc); arena->pinned_objs = Qnil; return TypedData_Wrap_Struct(klass, &Arena_type, arena); } diff --git a/ruby/tests/gc_test.rb b/ruby/tests/gc_test.rb index d7fecaeea108..5d48f464aee5 100755 --- a/ruby/tests/gc_test.rb +++ b/ruby/tests/gc_test.rb @@ -94,7 +94,6 @@ def test_generated_msg from = get_msg_proto3 data = A::B::C::TestMessage.encode(from) to = A::B::C::TestMessage.decode(data) - # This doesn't work for proto2 on JRuby because there is a nested required message. # A::B::Proto2::TestMessage has :required_msg which is of type: # A::B::Proto2::TestMessage so there is no way to generate a valid