mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Fix potential GC issue while iterating over weak refs
While walking over the list of subclasses for `include` and friends, we check whether the subclass is a garbage object. After the check, we allocate objects which might trigger GC and make the subclass garbage, even though before the allocation the subclass was not garbage. This is a sort of time-of-check-time-of-use issue. Fix this by saving the weak reference to a local variable, upgrading it to a strong reference while we do the allocation. It makes the code look slightly nicer even if it doesn't fix any runtime issues.
This commit is contained in:
parent
4acafdf632
commit
7448afccb3
Notes:
git
2022-05-06 06:37:33 +09:00
1 changed files with 9 additions and 8 deletions
17
class.c
17
class.c
|
@ -1383,17 +1383,18 @@ rb_prepend_module(VALUE klass, VALUE module)
|
|||
/* During lazy sweeping, iclass->klass could be a dead object that
|
||||
* has not yet been swept. */
|
||||
if (!rb_objspace_garbage_object_p(iclass->klass)) {
|
||||
if (klass_had_no_origin && klass_origin_m_tbl == RCLASS_M_TBL(iclass->klass)) {
|
||||
const VALUE subclass = iclass->klass;
|
||||
if (klass_had_no_origin && klass_origin_m_tbl == RCLASS_M_TBL(subclass)) {
|
||||
// backfill an origin iclass to handle refinements and future prepends
|
||||
rb_id_table_foreach(RCLASS_M_TBL(iclass->klass), clear_module_cache_i, (void *)iclass->klass);
|
||||
RCLASS_M_TBL(iclass->klass) = klass_m_tbl;
|
||||
VALUE origin = rb_include_class_new(klass_origin, RCLASS_SUPER(iclass->klass));
|
||||
RCLASS_SET_SUPER(iclass->klass, origin);
|
||||
RCLASS_SET_INCLUDER(origin, RCLASS_INCLUDER(iclass->klass));
|
||||
RCLASS_SET_ORIGIN(iclass->klass, origin);
|
||||
rb_id_table_foreach(RCLASS_M_TBL(subclass), clear_module_cache_i, (void *)subclass);
|
||||
RCLASS_M_TBL(subclass) = klass_m_tbl;
|
||||
VALUE origin = rb_include_class_new(klass_origin, RCLASS_SUPER(subclass));
|
||||
RCLASS_SET_SUPER(subclass, origin);
|
||||
RCLASS_SET_INCLUDER(origin, RCLASS_INCLUDER(subclass));
|
||||
RCLASS_SET_ORIGIN(subclass, origin);
|
||||
RICLASS_SET_ORIGIN_SHARED_MTBL(origin);
|
||||
}
|
||||
include_modules_at(iclass->klass, iclass->klass, module, FALSE);
|
||||
include_modules_at(subclass, subclass, module, FALSE);
|
||||
}
|
||||
|
||||
iclass = iclass->next;
|
||||
|
|
Loading…
Add table
Reference in a new issue