* variable.c (rb_const_set): fix WB miss.

WBs had located before creating reference between a klass
  and constant value. It causes GC bug.

    # pseudo code:
    WB(klass, value); # WB and remember klass
    st_insert(klass->const_table, const_id, value);

  `st_insert()' can cause GC before inserting `value' and
  forget `klass' from the remember set. After that, relationship
  between `klass' and `value' are created with constant table.
  Now, `value' can be young (shady) object and `klass' can be old
  object, without remembering `klass' object.
  At the next GC, old `klass' object will be skipped and
  young (shady) `value' will be miss-collected. -> GC bug

  Lesson: The place of a WB is important.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41396 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ko1 2013-06-18 19:50:44 +00:00
Родитель 81568a297b
Коммит 67d6aaca35
2 изменённых файлов: 25 добавлений и 4 удалений

Просмотреть файл

@ -1,3 +1,24 @@
Wed Jun 19 04:33:22 2013 Koichi Sasada <ko1@atdot.net>
* variable.c (rb_const_set): fix WB miss.
WBs had located before creating reference between a klass
and constant value. It causes GC bug.
# pseudo code:
WB(klass, value); # WB and remember klass
st_insert(klass->const_table, const_id, value);
`st_insert()' can cause GC before inserting `value' and
forget `klass' from the remember set. After that, relationship
between `klass' and `value' are created with constant table.
Now, `value' can be young (shady) object and `klass' can be old
object, without remembering `klass' object.
At the next GC, old `klass' object will be skipped and
young (shady) `value' will be miss-collected. -> GC bug
Lesson: The place of a WB is important.
Tue Jun 18 22:01:00 2013 Charlie Somerville <charliesome@ruby-lang.org>
* vm_insnhelper.c (vm_call_method): ensure methods of type

Просмотреть файл

@ -2155,7 +2155,7 @@ rb_const_set(VALUE klass, ID id, VALUE val)
/* for autoloading thread, keep the defined value to autoloading storage */
if (load && (ele = check_autoload_data(load)) && (ele->thread == rb_thread_current())) {
rb_vm_change_state();
ele->value = val;
ele->value = val; /* autoload_i is shady */
return;
}
/* otherwise, allow to override */
@ -2180,12 +2180,12 @@ rb_const_set(VALUE klass, ID id, VALUE val)
rb_vm_change_state();
ce = ALLOC(rb_const_entry_t);
MEMZERO(ce, rb_const_entry_t, 1);
ce->flag = visibility;
ce->line = rb_sourceline();
st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce);
OBJ_WRITE(klass, (VALUE *)&ce->value, val);
OBJ_WRITE(klass, (VALUE *)&ce->file, rb_sourcefilename());
ce->line = rb_sourceline();
st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce);
}
void