Skip to content

Commit b8a3f1b

Browse files
committed
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
1 parent 3bcf92d commit b8a3f1b

File tree

3 files changed

+10
-2
lines changed

3 files changed

+10
-2
lines changed

ext/objspace/depend

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ object_tracing.o: $(hdrdir)/ruby/missing.h
158158
object_tracing.o: $(hdrdir)/ruby/ruby.h
159159
object_tracing.o: $(hdrdir)/ruby/st.h
160160
object_tracing.o: $(hdrdir)/ruby/subst.h
161+
object_tracing.o: $(top_srcdir)/gc.h
161162
object_tracing.o: $(top_srcdir)/internal.h
162163
object_tracing.o: object_tracing.c
163164
object_tracing.o: objspace.h

ext/objspace/object_tracing.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
1414
**********************************************************************/
1515

16+
#include "gc.h"
1617
#include "internal.h"
1718
#include "ruby/debug.h"
1819
#include "objspace.h"
@@ -121,6 +122,10 @@ freeobj_i(VALUE tpval, void *data)
121122
st_data_t v;
122123
struct allocation_info *info;
123124

125+
/* Modifying the st table can cause allocations, which can trigger GC.
126+
* Since freeobj_i is called during GC, it must not trigger another GC. */
127+
VALUE gc_disabled = rb_gc_disable_no_rest();
128+
124129
if (arg->keep_remains) {
125130
if (st_lookup(arg->object_table, obj, &v)) {
126131
info = (struct allocation_info *)v;
@@ -135,6 +140,8 @@ freeobj_i(VALUE tpval, void *data)
135140
ruby_xfree(info);
136141
}
137142
}
143+
144+
if (gc_disabled == Qfalse) rb_gc_enable();
138145
}
139146

140147
static int

gc.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,6 @@ int ruby_get_stack_grow_direction(volatile VALUE *addr);
116116
const char *rb_obj_info(VALUE obj);
117117
const char *rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj);
118118

119-
VALUE rb_gc_disable_no_rest(void);
120-
121119
struct rb_thread_struct;
122120

123121
size_t rb_size_pool_slot_size(unsigned char pool_id);
@@ -142,6 +140,8 @@ void rb_objspace_each_objects_without_setup(
142140

143141
size_t rb_gc_obj_slot_size(VALUE obj);
144142

143+
VALUE rb_gc_disable_no_rest(void);
144+
145145
RUBY_SYMBOL_EXPORT_END
146146

147147
#endif /* RUBY_GC_H */

0 commit comments

Comments
 (0)