Bug #19701
openThe rb_classext_t::classpath field is not marked for T_ICLASS
Description
I am hacking Ruby to dump information about some objects, and I found that the rb_classext_t::classpath
field for T_ICLASS
objects sometimes contains dangling references to dead objects.
The commit https://github.com/ruby/ruby/commit/081cc4eb283cb01ddffb364397e5175dbfacab66 set the classpath
field of rb_mRubyVMFrozenCore
to a string "FrozenCore" so that it can be dumped using the rb_dump_literal
function.
However, in gc_mark_children
, if the obj
is a T_ICLASS
, the RCLASS_EXT(obj)->classpath
will not be marked. As a result, if rb_mRubyVMFrozenCore
is the only object that holds a reference to the string "FrozenCore", the string will be considered garbage and reclaimed during a GC, and the classpath
will contain a dangling pointer.
There are two solutions to this problem. We can take one of the approaches below (not both).
- Let the GC mark the
classpath
field. I drafted a pull request here: https://github.com/ruby/ruby/pull/7875 - Revert the commit https://github.com/ruby/ruby/commit/081cc4eb283cb01ddffb364397e5175dbfacab66
Marking the classpath
field in GC will keep the rb_dump_literal
function working. For debug purposes, we can also use that field to identify what object a given T_ICLASS
is. Adding one marked field may make GC slower, but I don't think it will be observable because there are far less T_ICLASS
objects than ordinary objects.
If we reverting the commit above, the classpath
will always be blank for all T_ICLASS
objects. (Question: How do we enforce it?) It will also save some memory by keeping less strings alive. However, currently, "FrozenCore" seems to be the only T_OBJECT
that has its classpath set, and it may not result in significant memory saving. I don't know what purpose the rb_dump_literal
function originally served. Maybe it is still important. Maybe it is safe to remove now.
Which of the two approaches should we take? It looks like each of them has its pros and cons.