From 47cac4131433b1b0a39f33116dfe14084896fc98 Mon Sep 17 00:00:00 2001 From: Luke Gruber Date: Mon, 5 Oct 2026 11:44:12 -0400 Subject: [PATCH] Fix ObjectSpace.each_iseq to not yield during VM lock rb_objspace_each_objects() takes the VM lock (with a barrier), so you can't run Ruby code in the callback function. It is okay to trigger GC during the callback function, so collect each iseq in an array and then iterate over them after the walk. Hopefully there aren't too many iseqs and performance doesn't suffer too much. --- ext/debug/iseq_collector.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ext/debug/iseq_collector.c b/ext/debug/iseq_collector.c index 6b8d355a9..7d6ffc022 100644 --- a/ext/debug/iseq_collector.c +++ b/ext/debug/iseq_collector.c @@ -56,14 +56,19 @@ iseq_i(void *vstart, void *vend, size_t stride, void *ptr) static void each_iseq_i(VALUE v, void *ptr) { - rb_yield(rb_iseqw_new(v)); + VALUE ary = (VALUE)ptr; + rb_ary_push(ary, v); } static VALUE each_iseq(VALUE self) { - struct iseq_i_data data = {each_iseq_i, NULL}; + VALUE ary = rb_ary_new(); + struct iseq_i_data data = {each_iseq_i, (void*)ary}; rb_objspace_each_objects(iseq_i, &data); + for (long i = 0; i < RARRAY_LEN(ary); i++) { + rb_yield(rb_iseqw_new(RARRAY_AREF(ary, i))); + } return Qnil; }