summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gc.c12
-rw-r--r--include/ruby/internal/gc.h13
2 files changed, 18 insertions, 7 deletions
diff --git a/gc.c b/gc.c
index 2386ec422c..bcc3f87642 100644
--- a/gc.c
+++ b/gc.c
@@ -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);