From: Eric Wong Date: 2011-07-25T23:13:06+09:00 Subject: [ruby-core:38498] Re: [Ruby 1.9 - Bug #5047] Segfault (most likely involving require) Yusuke ENDOH wrote: > 2011/7/25 Eric Wong : > > sidenote: I didn't realize xmalloc() (via rb_unlink_method_entry) is > > safe/allowed inside bm_free(); but apparently it's only rb_new_obj() > > that's prevented inside GC. > > Good point. I was not aware of this. > Indeed, GC does not occur recursively even if vm_xmalloc is called > during GC. But NoMemoryError may be raised from bm_free()... It > will probably make the interpreter state inconsistent, so I guess > it is not possible to sanely continue the execution by rescue'ing > the exception. > But I have no solution about the case. Frankly speaking, I think > we can do nothing if just few dozens byte allocation is failed. We can pre-allocate the unlinked_method_entry_list_entry struct in the METHOD struct and then push it into unlinked_method_entry_list in bm_free (untested patch below): --- a/proc.c +++ b/proc.c @@ -19,6 +19,7 @@ struct METHOD { VALUE rclass; ID id; rb_method_entry_t *me; + struct unlinked_method_entry_list_entry *ume; }; VALUE rb_cUnboundMethod; @@ -868,7 +869,11 @@ static void bm_free(void *ptr) { struct METHOD *data = ptr; - rb_unlink_method_entry(data->me); + struct unlinked_method_entry_list_entry *ume = data->ume; + + ume->me = data->me; + ume->next = GET_VM()->unlinked_method_entry_list; + GET_VM()->unlinked_method_entry_list = ume; xfree(ptr); } @@ -978,6 +983,7 @@ mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope) data->me = me2; *data->me = *me; data->me->def->alias_count++; + data->ume = ALLOC(struct unlinked_method_entry_list_entry); OBJ_INFECT(method, klass); @@ -1088,6 +1094,7 @@ method_unbind(VALUE obj) *data->me = *orig->me; if (orig->me->def) orig->me->def->alias_count++; data->rclass = orig->rclass; + data->ume = ALLOC(struct unlinked_method_entry_list_entry); OBJ_INFECT(method, obj); return method; -- Eric Wong