diff options
-rw-r--r-- | gc.c | 12 | ||||
-rw-r--r-- | include/ruby/internal/gc.h | 13 |
2 files changed, 18 insertions, 7 deletions
@@ -9209,10 +9209,16 @@ rb_gc_register_address(VALUE *addr) tmp->varptr = addr; global_list = tmp; - /* obj has to be guarded here because the allocation above could trigger a - * GC. However, C extensions could pass a pointer to a global variable - * which does not exist on the stack and thus could get swept. */ + /* + * Because some C extensions have assignment-then-register bugs, + * we guard `obj` here so that it would not get swept defensively. + */ RB_GC_GUARD(obj); + if (0 && !SPECIAL_CONST_P(obj)) { + rb_warn("Object is assigned to registering address already: %"PRIsVALUE, + rb_obj_class(obj)); + rb_print_backtrace(); + } } void diff --git a/include/ruby/internal/gc.h b/include/ruby/internal/gc.h index bc81883e0e..205830954e 100644 --- a/include/ruby/internal/gc.h +++ b/include/ruby/internal/gc.h @@ -399,10 +399,15 @@ VALUE rb_gc_latest_gc_info(VALUE key_or_buf); void rb_gc_adjust_memory_usage(ssize_t diff); /** - * Inform the garbage collector that `valptr` points to a live Ruby object that - * should not be moved. Note that extensions should use this API on global - * constants instead of assuming constants defined in Ruby are always alive. - * Ruby code can remove global constants. + * Inform the garbage collector that the global or static variable pointed by + * `valptr` stores a live Ruby object that should not be moved. Note that + * extensions should use this API on global constants instead of assuming + * constants defined in Ruby are always alive. Ruby code can remove global + * constants. + * + * Because this registration itself has a possibility to trigger a GC, this + * function must be called before any GC-able objects is assigned to the + * address pointed by `valptr`. */ void rb_gc_register_address(VALUE *valptr); |