Just got back in, fired up email and see that Hiroshi-san delivered the awesome good-fu once again! :) :) :)
Jarmo: you likely already know the ruby memory mgmt code Hiroshi described, but if not, here's a snippet walkthrough for future reference. Hiroshi, please correct me if I've mislead.
`ALLOC` is a macro defined in `include/ruby/ruby.h:1035` as
#define ALLOC(type) ((type*)xmalloc(sizeof(type)))
and `xmalloc` is aliased in `include/ruby/defines.h:64` as
#define xmalloc ruby_xmalloc
with `ruby_xmalloc` defined in `gc.c:856` as
void *
ruby_xmalloc(size_t size)
{
return vm_xmalloc(&rb_objspace, size);
}
leading to a `vm_xmalloc` definition in `gc.c:791` of
static void *
vm_xmalloc(rb_objspace_t *objspace, size_t size)
{
void *mem;
size = vm_malloc_prepare(objspace, size);
TRY_WITH_GC(mem = malloc(size));
return vm_malloc_fixup(objspace, mem, size);
}
This does some pre and post-magic around a normal `malloc`. The `vm_malloc_prepare` pre-magic in `gc.c:748` will do a GC in the following case (Hiroshi forced the immediate fail with `GC.stress = true` in your script)
if ((ruby_gc_stress && !ruby_disable_gc_stress) ||
(malloc_increase+size) > malloc_limit) {
garbage_collect_with_gvl(objspace);
}
Finally, `garbage_collect_with_gvl` at `gc.c:727`
static int
garbage_collect_with_gvl(rb_objspace_t *objspace)
{
if (dont_gc) return TRUE;
if (ruby_thread_has_gvl_p()) {
return garbage_collect(objspace);
}
else {
if (ruby_native_thread_p()) {
return (int)(VALUE)rb_thread_call_with_gvl(gc_with_gvl, (void *)objspace);
}
else {
/* no ruby thread */
fprintf(stderr, "[FATAL] failed to allocate memory\n");
exit(EXIT_FAILURE);
}
}
}
and your sample code got the last `else` clause.
However, as Hiroshi shows, if WDM had used it's internal `WDM_ALLOC` defined in `ext/wdm/memory.h:23` as
`#define WDM_ALLOC(type) ((type*)wdm_memory_malloc(sizeof(type)))
using `wdm_memory_malloc` in `ext/wdm/memory.c:6`
void *
wdm_memory_malloc (size_t size)
{
void *memory = malloc(size);
if ( memory == NULL ) {
rb_fatal("failed to allocate memory");
}
return memory;
}
instead of ruby's GC-using `ALLOC/xmalloc`, things should work since (from what I've seen so far) WDM does it's own memory mgt via `malloc/free` and shouldn't mix with ruby's memory mgmt.
I'm trying Hiroshi's patch tomorrow on Win7 32bit with your sample code. It will be interesting to hear if it solves the WDM bug.
My money's on Hiroshi :)
Jon
---
Fail fast. Fail often. Fail publicly. Learn. Adapt. Repeat.
http://thecodeshop.github.com |
http://jonforums.github.com/
twitter: @jonforums