From 64007fc57f360eab4b18b26389719a85f45b25c3 Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Fri, 5 Nov 2021 09:36:44 +0900 Subject: [PATCH] class.c (Class#descendants): Ingore subclasses created after estimation It is theoretically possible if a finalizer creates a subclass. --- class.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/class.c b/class.c index fc79c415b3..a22bb756a5 100644 --- a/class.c +++ b/class.c @@ -1340,6 +1340,7 @@ struct subclass_traverse_data { VALUE *buffer; long count; + long maxcount; }; static void @@ -1348,7 +1349,7 @@ class_descendants_recursive(VALUE klass, VALUE v) struct subclass_traverse_data *data = (struct subclass_traverse_data *) v; if (BUILTIN_TYPE(klass) == T_CLASS && !FL_TEST(klass, FL_SINGLETON)) { - if (data->buffer) { + if (data->buffer && (data->count < data->maxcount || data->maxcount == -1)) { data->buffer[data->count] = klass; } data->count++; @@ -1377,13 +1378,14 @@ class_descendants_recursive(VALUE klass, VALUE v) VALUE rb_class_descendants(VALUE klass) { - struct subclass_traverse_data data = { NULL, 0 }; + struct subclass_traverse_data data = { NULL, 0, -1 }; // estimate the count of subclasses rb_class_foreach_subclass(klass, class_descendants_recursive, (VALUE) &data); // this allocation may cause GC which may reduce the subclasses data.buffer = ALLOC_N(VALUE, data.count); + data.maxcount = data.count; data.count = 0; // enumerate subclasses