diff options
author | nagachika <nagachika@ruby-lang.org> | 2024-01-18 12:57:01 +0900 |
---|---|---|
committer | nagachika <nagachika@ruby-lang.org> | 2024-01-18 12:57:01 +0900 |
commit | 99c9aeef4b4417120e30b145cf98e1bc68a2a0de (patch) | |
tree | 92c572cbdc8ce5c6d5401c4efbe15d0de16cca51 | |
parent | 3302e251dccec1e981945ab19d316d0856c68bf6 (diff) |
merge revision(s) b8a3f1bd456f92866c4a7bd83235f78c574784a8:
Fix crash in tracing object allocations
ObjectSpace.trace_object_allocations_start could crash since it adds a
TracePoint for when objects are freed. However, TracePoint could crash
since it modifies st tables while inside the GC that is trying to free
the object. This could cause a memory allocation to happen which would
crash if it triggers another GC.
See a crash log: http://ci.rvm.jp/results/trunk@ruby-sp1/4373707
---
ext/objspace/depend | 1 +
ext/objspace/object_tracing.c | 7 +++++++
gc.h | 4 ++--
3 files changed, 10 insertions(+), 2 deletions(-)
-rw-r--r-- | ext/objspace/depend | 1 | ||||
-rw-r--r-- | ext/objspace/object_tracing.c | 7 | ||||
-rw-r--r-- | gc.h | 4 | ||||
-rw-r--r-- | version.h | 2 |
4 files changed, 11 insertions, 3 deletions
diff --git a/ext/objspace/depend b/ext/objspace/depend index e76cfa963f..52797664e0 100644 --- a/ext/objspace/depend +++ b/ext/objspace/depend @@ -158,6 +158,7 @@ object_tracing.o: $(hdrdir)/ruby/missing.h object_tracing.o: $(hdrdir)/ruby/ruby.h object_tracing.o: $(hdrdir)/ruby/st.h object_tracing.o: $(hdrdir)/ruby/subst.h +object_tracing.o: $(top_srcdir)/gc.h object_tracing.o: $(top_srcdir)/internal.h object_tracing.o: object_tracing.c object_tracing.o: objspace.h diff --git a/ext/objspace/object_tracing.c b/ext/objspace/object_tracing.c index 0bf866a8f1..8c54d51eab 100644 --- a/ext/objspace/object_tracing.c +++ b/ext/objspace/object_tracing.c @@ -13,6 +13,7 @@ **********************************************************************/ +#include "gc.h" #include "internal.h" #include "ruby/debug.h" #include "objspace.h" @@ -121,6 +122,10 @@ freeobj_i(VALUE tpval, void *data) st_data_t v; struct allocation_info *info; + /* Modifying the st table can cause allocations, which can trigger GC. + * Since freeobj_i is called during GC, it must not trigger another GC. */ + VALUE gc_disabled = rb_gc_disable_no_rest(); + if (arg->keep_remains) { if (st_lookup(arg->object_table, obj, &v)) { info = (struct allocation_info *)v; @@ -135,6 +140,8 @@ freeobj_i(VALUE tpval, void *data) ruby_xfree(info); } } + + if (gc_disabled == Qfalse) rb_gc_enable(); } static int @@ -116,8 +116,6 @@ int ruby_get_stack_grow_direction(volatile VALUE *addr); const char *rb_obj_info(VALUE obj); const char *rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj); -VALUE rb_gc_disable_no_rest(void); - struct rb_thread_struct; size_t rb_size_pool_slot_size(unsigned char pool_id); @@ -142,6 +140,8 @@ void rb_objspace_each_objects_without_setup( size_t rb_gc_obj_slot_size(VALUE obj); +VALUE rb_gc_disable_no_rest(void); + RUBY_SYMBOL_EXPORT_END #endif /* RUBY_GC_H */ @@ -11,7 +11,7 @@ # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 2 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 155 +#define RUBY_PATCHLEVEL 156 #include "ruby/version.h" #include "ruby/internal/abi.h" |