From 8cfa1773652264837eab45cd907b1a99e9e20980 Mon Sep 17 00:00:00 2001 From: shyouhei Date: Mon, 7 Jul 2008 06:01:50 +0000 Subject: merge revision(s) 17832: * eval.c (rb_longjmp): duplicate the thrown exception to set backtrace if it was frozen. clear all raised flags. * eval.c (stack_check): leave clearing flag to rb_longjmp. * eval.c (rb_thread_set_raised, rb_thread_reset_raised): use generic flags. * eval.c (Init_Proc), gc.c (Init_GC): freeze preallocated special exceptions. * gc.c (rb_memerror): use thread raised flag instead of static flag, and raise nomem_error without backtrace if failed to make backtrace. [ruby-dev:34724] * gc.c (ruby_xmalloc): increase malloc_increase only if malloc succeeds. failed malloc size can be huge. it may increase malloc_limit too big which cause less GC and memory full. (ruby_xrealloc): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_6@17928 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- gc.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'gc.c') diff --git a/gc.c b/gc.c index be883583bb..807d8eb2ec 100644 --- a/gc.c +++ b/gc.c @@ -74,16 +74,22 @@ static void run_final(); static VALUE nomem_error; static void garbage_collect(); +NORETURN(void rb_exc_jump _((VALUE))); + void rb_memerror() { - static int recurse = 0; + rb_thread_t th = rb_curr_thread; - if (!nomem_error || (recurse > 0 && rb_safe_level() < 4)) { + if (!nomem_error || + (rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) { fprintf(stderr, "[FATAL] failed to allocate memory\n"); exit(1); } - recurse++; + if (rb_thread_raised_p(th, RAISED_NOMEMORY)) { + rb_exc_jump(nomem_error); + } + rb_thread_raised_set(th, RAISED_NOMEMORY); rb_exc_raise(nomem_error); } @@ -97,9 +103,8 @@ ruby_xmalloc(size) rb_raise(rb_eNoMemError, "negative allocation size (or too big)"); } if (size == 0) size = 1; - malloc_increase += size; - if (malloc_increase > malloc_limit) { + if ((malloc_increase+size) > malloc_limit) { garbage_collect(); } RUBY_CRITICAL(mem = malloc(size)); @@ -110,6 +115,7 @@ ruby_xmalloc(size) rb_memerror(); } } + malloc_increase += size; return mem; } @@ -138,7 +144,6 @@ ruby_xrealloc(ptr, size) } if (!ptr) return xmalloc(size); if (size == 0) size = 1; - malloc_increase += size; RUBY_CRITICAL(mem = realloc(ptr, size)); if (!mem) { garbage_collect(); @@ -147,6 +152,7 @@ ruby_xrealloc(ptr, size) rb_memerror(); } } + malloc_increase += size; return mem; } @@ -2064,6 +2070,8 @@ Init_GC() rb_global_variable(&nomem_error); nomem_error = rb_exc_new2(rb_eNoMemError, "failed to allocate memory"); + OBJ_TAINT(nomem_error); + OBJ_FREEZE(nomem_error); rb_define_method(rb_mKernel, "hash", rb_obj_id, 0); rb_define_method(rb_mKernel, "__id__", rb_obj_id, 0); -- cgit v1.2.3