diff -rux '*.o' ruby-1.8.7-p72/ChangeLog ruby-1.8.7-mbari/ChangeLog
--- ruby-1.8.7-p72/ChangeLog	2008-12-13 23:32:29.000000000 -0800
+++ ruby-1.8.7-mbari/ChangeLog	2008-12-13 23:17:30.000000000 -0800
@@ -1,3 +1,18 @@
+Tue Dec 13  6:10:36 2008  Brent Roman  <brent@mbari.org>
+
+        * eval.c:  update stack extent just before and after every setjmp
+
+        * gc.c:  replaced rb_gc_stress with gc_getlimit and setlimit
+                 update stack extent after every xmalloc and xrealloc
+                 export rb_gc_stack_grow_direction if not known at compile time
+                 removed dynamic adjustment of malloc_limit
+                 removed workaround for obsolete gcc 2.7.2.3 bug                 
+
+        * signal.h: don't try to clear stress after segsegv.  It's a too late.
+        
+        * rubysig.h:  CHECK_INTS clears ghost references off stack
+
+
 Tue Dec 12  6:11:36 2008  Brent Roman  <brent@mbari.org>
 
         * eval.c:  exclude other thread's stack frames from current one
diff -rux '*.o' ruby-1.8.7-p72/eval.c ruby-1.8.7-mbari/eval.c
--- ruby-1.8.7-p72/eval.c	2008-12-13 23:32:29.000000000 -0800
+++ ruby-1.8.7-mbari/eval.c	2008-12-13 23:23:06.000000000 -0800
@@ -3,7 +3,7 @@
   eval.c -
 
   $Author: brent $
-  $Date: 2008/12/13 06:34:34 $
+  $Date: 2008/12/14 07:23:06 $
   created at: Thu Jun 10 14:22:17 JST 1993
 
   Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -1027,7 +1027,14 @@
 #define PROT_LAMBDA INT2FIX(2)	/* 5 */
 #define PROT_YIELD  INT2FIX(3)	/* 7 */
 
 #define EXEC_TAG()    ruby_setjmp(((void)0), prot_tag->buf)
+
+static inline 
+int up_stk_extent(int status)
+{
+  rb_gc_update_stack_extent();
+  return status;
+}
 
 #define JUMP_TAG(st) do {		\
     ruby_frame = prot_tag->frame;	\
@@ -10419,7 +10426,7 @@
     stkBase = (void *)th->stk_start;
     stkSize = th->stk_len * sizeof(VALUE);
 #if STACK_GROW_DIRECTION == 0
-    if ((VALUE *)&th < rb_gc_stack_start)
+    if (rb_gc_stack_grow_direction < 0)
 #endif
 #if STACK_GROW_DIRECTION <= 0
       stkBase -= stkSize;
@@ -10697,8 +10704,8 @@
     return 1;
 }
 
-#define THREAD_SAVE_CONTEXT(th) \
-    (rb_thread_switch(ruby_setjmp(rb_thread_save_context(th), (th)->context)))
+#define THREAD_SAVE_CONTEXT(th) (rb_thread_switch(up_stk_extent( \
+                  ruby_setjmp(rb_thread_save_context(th), (th)->context))))
 
 NORETURN(static void rb_thread_restore_context _((rb_thread_t,int)));
 NORETURN(NOINLINE(static void rb_thread_restore_context_0(rb_thread_t,int,void*)));
diff -rux '*.o' ruby-1.8.7-p72/gc.c ruby-1.8.7-mbari/gc.c
--- ruby-1.8.7-p72/gc.c	2008-12-13 23:32:29.000000000 -0800
+++ ruby-1.8.7-mbari/gc.c	2008-12-13 23:23:34.000000000 -0800
@@ -3,7 +3,7 @@
   gc.c -
 
   $Author: brent $
-  $Date: 2008/12/13 05:47:46 $
+  $Date: 2008/12/14 07:23:34 $
   created at: Tue Oct  5 09:44:46 JST 1993
 
   Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -70,13 +70,66 @@
 #endif
 #endif
 
-static unsigned long malloc_increase = 0;
+
+size_t rb_gc_malloc_increase = 0;
+#define malloc_increase rb_gc_malloc_increase
 static unsigned long malloc_limit = GC_MALLOC_LIMIT;
+size_t rb_gc_malloc_limit = GC_MALLOC_LIMIT-GC_MALLOC_LIMIT/8;
+
+/*
+ *  call-seq:
+ *     GC.limit    => increase limit in bytes
+ *
+ *  Get the # of bytes that may be allocated before triggering
+ *  a mark and sweep by the garbarge collector to reclaim unused storage.
+ *
+ */
+static VALUE gc_getlimit(VALUE mod)
+{
+  return ULONG2NUM(malloc_limit);
+}
+
+/*
+ *  call-seq:
+ *     GC.limit=   => updated increase limit in bytes
+ *
+ *  Set the # of bytes that may be allocated before triggering
+ *  a mark and sweep by the garbarge collector to reclaim unused storage.
+ *  Attempts to set the GC.limit= less than 0 will be ignored.
+ *
+ *     GC.limit=5000000   #=> 5000000
+ *     GC.limit           #=> 5000000
+ *     GC.limit=-50       #=> 5000000
+ *     GC.limit=0         #=> 0
+ *
+ */
+static VALUE gc_setlimit(VALUE mod, VALUE newLimit)
+{
+  long limit = NUM2LONG(newLimit);
+  if (limit < 0) return gc_getlimit(mod);
+  malloc_limit = limit;
+  rb_gc_malloc_limit = malloc_limit - malloc_limit/8;
+  return newLimit;
+}
+
+
+/*
+ *  call-seq:
+ *     GC.increase
+ *
+ *  Get # of bytes that have been allocated since the last mark & sweep
+ *
+ */
+static VALUE gc_increase(VALUE mod)
+{
+  return ULONG2NUM(malloc_increase);
+}
+
+
 static void run_final();
 static VALUE nomem_error;
 static void garbage_collect();
 
-int ruby_gc_stress = 0;
 
 NORETURN(void rb_exc_jump _((VALUE)));
 
@@ -97,40 +150,6 @@
     rb_exc_raise(nomem_error);
 }
 
-/*
- *  call-seq:
- *    GC.stress                 => true or false
- *
- *  returns current status of GC stress mode.
- */
-
-static VALUE
-gc_stress_get(self)
-    VALUE self;
-{
-    return ruby_gc_stress ? Qtrue : Qfalse;
-}
-
-/*
- *  call-seq:
- *    GC.stress = bool          => bool
- *
- *  updates GC stress mode.
- *
- *  When GC.stress = true, GC is invoked for all GC opportunity:
- *  all memory and object allocation.
- *
- *  Since it makes Ruby very slow, it is only for debugging.
- */
-
-static VALUE
-gc_stress_set(self, bool)
-    VALUE self, bool;
-{
-    rb_secure(2);
-    ruby_gc_stress = RTEST(bool);
-    return bool;
-}
 
 void *
 ruby_xmalloc(size)
@@ -143,8 +162,9 @@
     }
     if (size == 0) size = 1;
 
-    if (ruby_gc_stress || (malloc_increase+size) > malloc_limit) {
+    if ((malloc_increase+=size) > malloc_limit) {
 	garbage_collect();
+        malloc_increase = size;
     }
     RUBY_CRITICAL(mem = malloc(size));
     if (!mem) {
@@ -154,8 +174,7 @@
 	    rb_memerror();
 	}
     }
-    malloc_increase += size;
-
+    rb_gc_update_stack_extent();
     return mem;
 }
 
@@ -183,7 +202,10 @@
     }
     if (!ptr) return xmalloc(size);
     if (size == 0) size = 1;
-    if (ruby_gc_stress) garbage_collect();
+    if ((malloc_increase+=size) > malloc_limit) {
+	garbage_collect();
+        malloc_increase = size;
+    }
     RUBY_CRITICAL(mem = realloc(ptr, size));
     if (!mem) {
 	garbage_collect();
@@ -192,8 +214,7 @@
 	    rb_memerror();
         }
     }
-    malloc_increase += size;
-
+    rb_gc_update_stack_extent();
     return mem;
 }
 
@@ -433,7 +454,7 @@
     if (during_gc)
 	rb_bug("object allocation during garbage collection phase");
 
-    if (ruby_gc_stress || !freelist) garbage_collect();
+    if (!malloc_limit || !freelist) garbage_collect();
 
     obj = (VALUE)freelist;
     freelist = freelist->as.free.next;
@@ -468,6 +489,9 @@
 VALUE *rb_gc_register_stack_start = 0;
 #endif
 
+VALUE *rb_gc_stack_end = (VALUE *)STACK_GROW_DIRECTION;
+
+
 #ifdef DJGPP
 /* set stack size (http://www.delorie.com/djgpp/v2faq/faq15_9.html) */
 unsigned int _stklen = 0x180000; /* 1.5 kB */
@@ -518,18 +542,15 @@
 #elif STACK_GROW_DIRECTION < 0
 # define STACK_UPPER(x, a, b) b
 #else
-static int grow_direction;
+int rb_gc_stack_grow_direction;
 static int
 stack_grow_direction(addr)
     VALUE *addr;
 {
     SET_STACK_END;
-
-    if (STACK_END > addr) return grow_direction = 1;
-    return grow_direction = -1;
+    return rb_gc_stack_grow_direction = STACK_END > addr ? 1 : -1;
 }
-# define stack_growup_p(x) ((grow_direction ? grow_direction : stack_grow_direction(x)) > 0)
-# define STACK_UPPER(x, a, b) (stack_growup_p(x) ? a : b)
+# define STACK_UPPER(x, a, b) (rb_gc_stack_grow_direction > 0 ? a : b)
 #endif
 
 #define GC_WATER_MARK 512
@@ -1097,13 +1118,12 @@
     RVALUE *p, *pend, *final_list;
     int freed = 0;
     int i;
-    unsigned long live = 0;
     unsigned long free_min = 0;
 
     for (i = 0; i < heaps_used; i++) {
         free_min += heaps[i].limit;
     }
-    free_min = free_min * 0.2;
+    free_min /= 5;
     if (free_min < FREE_MIN)
         free_min = FREE_MIN;
 
@@ -1157,7 +1177,6 @@
 	    }
 	    else {
 		RBASIC(p)->flags &= ~FL_MARK;
-		live++;
 	    }
 	    p++;
 	}
@@ -1174,10 +1193,6 @@
 	    freed += n;
 	}
     }
-    if (malloc_increase > malloc_limit) {
-	malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed);
-	if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
-    }
     malloc_increase = 0;
     if (freed < free_min) {
 	add_heap();
@@ -1373,7 +1388,7 @@
 garbage_collect()
 {
     struct gc_list *list;
-    struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug??  */
+    struct FRAME * frame;
     jmp_buf save_regs_gc_mark;
     SET_STACK_END;
 
@@ -1421,7 +1436,7 @@
 #elif STACK_GROW_DIRECTION > 0
     rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1);
 #else
-    if ((VALUE*)STACK_END < rb_gc_stack_start)
+    if (rb_gc_stack_grow_direction < 0)
 	rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start);
     else
 	rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END + 1);
@@ -2086,12 +2101,16 @@
 {
     VALUE rb_mObSpace;
 
+#if !STACK_GROW_DIRECTION
+    rb_gc_stack_end = stack_grow_direction(&rb_mObSpace);
+#endif
     rb_mGC = rb_define_module("GC");
     rb_define_singleton_method(rb_mGC, "start", rb_gc_start, 0);
     rb_define_singleton_method(rb_mGC, "enable", rb_gc_enable, 0);
     rb_define_singleton_method(rb_mGC, "disable", rb_gc_disable, 0);
-    rb_define_singleton_method(rb_mGC, "stress", gc_stress_get, 0);
-    rb_define_singleton_method(rb_mGC, "stress=", gc_stress_set, 1);
+    rb_define_singleton_method(rb_mGC, "limit", gc_getlimit, 0);
+    rb_define_singleton_method(rb_mGC, "limit=", gc_setlimit, 1);
+    rb_define_singleton_method(rb_mGC, "increase", gc_increase, 0);
     rb_define_method(rb_mGC, "garbage_collect", rb_gc_start, 0);
 
     rb_mObSpace = rb_define_module("ObjectSpace");
diff -rux '*.o' ruby-1.8.7-p72/rubysig.h ruby-1.8.7-mbari/rubysig.h
--- ruby-1.8.7-p72/rubysig.h	2007-02-12 15:01:19.000000000 -0800
+++ ruby-1.8.7-mbari/rubysig.h	2008-12-13 23:24:10.000000000 -0800
@@ -2,8 +2,8 @@
 
   rubysig.h -
 
-  $Author: shyouhei $
-  $Date: 2007-02-13 08:01:19 +0900 (Tue, 13 Feb 2007) $
+  $Author: brent $
+  $Date: 2008/12/14 07:24:10 $
   created at: Wed Aug 16 01:15:38 JST 1995
 
   Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -81,7 +81,50 @@
 void rb_thread_schedule _((void));
 #if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE)
 RUBY_EXTERN int rb_thread_pending;
+
+EXTERN size_t rb_gc_malloc_increase;
+EXTERN size_t rb_gc_malloc_limit;
+EXTERN VALUE *rb_gc_stack_end;
+EXTERN int *rb_gc_stack_grow_direction;  /* -1 for down or 1 for up */
+#define __stack_zero_up(end,sp)  while (end >= ++sp) *sp=0
+#define __stack_grown_up  (rb_gc_stack_end > (VALUE *)alloca(0))
+#define __stack_zero_down(end,sp)  while (end <= --sp) *sp=0
+#define __stack_grown_down  (rb_gc_stack_end < (VALUE *)alloca(0))
+
+#if STACK_GROW_DIRECTION > 0
+#define __stack_zero(end,sp)  __stack_zero_up(end,sp)
+#define __stack_grown  __stack_grown_up
+#elif STACK_GROW_DIRECTION < 0
+#define __stack_zero(end,sp)  __stack_zero_down(end,sp)
+#define __stack_grown  __stack_grown_down
+#else  /* limp along if stack direction can't be determined at compile time */
+#define __stack_zero(end,sp) if (rb_gc_stack_grow_direction<0) \
+        __stack_zero_down(end,sp); else __stack_zero_up(end,sp);
+#define __stack_grown  \
+        (rb_gc_stack_grow_direction<0 ? __stack_grown_down : __stack_grown_up)
+#endif
+ 
+/*
+  zero the memory that was (recently) part of the stack
+  but is no longer.  Invoke when stack is deep to mark its extent
+  and when it is shallow to wipe it
+*/
+#define rb_gc_wipe_stack() {     \
+  VALUE *sp = alloca(0);         \
+  VALUE *end = rb_gc_stack_end;  \
+  rb_gc_stack_end = sp;          \
+  __stack_zero(end, sp);   \
+}
+
+/*
+  Update our record of maximum stack extent without zeroing unused stack
+*/
+#define rb_gc_update_stack_extent() \
+    if __stack_grown rb_gc_stack_end = alloca(0);
+
+
 # define CHECK_INTS do {\
+    rb_gc_wipe_stack(); \
     if (!(rb_prohibit_interrupt || rb_thread_critical)) {\
         if (rb_thread_pending) rb_thread_schedule();\
 	if (rb_trap_pending) rb_trap_exec();\
@@ -92,6 +135,7 @@
 RUBY_EXTERN int rb_thread_tick;
 #define THREAD_TICK 500
 #define CHECK_INTS do {\
+    rb_gc_wipe_stack(); \
     if (!(rb_prohibit_interrupt || rb_thread_critical)) {\
 	if (rb_thread_tick-- <= 0) {\
 	    rb_thread_tick = THREAD_TICK;\
diff -rux '*.o' ruby-1.8.7-p72/signal.c ruby-1.8.7-mbari/signal.c
--- ruby-1.8.7-p72/signal.c	2008-06-06 03:39:57.000000000 -0700
+++ ruby-1.8.7-mbari/signal.c	2008-12-13 23:24:39.000000000 -0800
@@ -2,8 +2,8 @@
 
   signal.c -
 
-  $Author: knu $
-  $Date: 2008-06-06 19:39:57 +0900 (Fri, 06 Jun 2008) $
+  $Author: brent $
+  $Date: 2008/12/14 07:24:39 $
   created at: Tue Dec 20 10:13:44 JST 1994
 
   Copyright (C) 1993-2003 Yukihiro Matsumoto
@@ -629,8 +629,6 @@
     }
 #endif
 
-    extern int ruby_gc_stress;
-    ruby_gc_stress = 0;
     rb_bug("Segmentation fault");
 }
 #endif
diff -rux '*.o' ruby-1.8.7-p72/version.h ruby-1.8.7-mbari/version.h
--- ruby-1.8.7-p72/version.h	2008-12-13 23:32:29.000000000 -0800
+++ ruby-1.8.7-mbari/version.h	2008-12-13 20:47:17.000000000 -0800
@@ -1,7 +1,7 @@
 #define RUBY_VERSION "1.8.7"
-#define RUBY_RELEASE_DATE "2008-12-12"
+#define RUBY_RELEASE_DATE "2008-12-13"
 #define RUBY_VERSION_CODE 187
-#define RUBY_RELEASE_CODE 20081212
+#define RUBY_RELEASE_CODE 20081213
 #define RUBY_PATCHLEVEL 72
 
 #define RUBY_VERSION_MAJOR 1
@@ -9,7 +9,7 @@
 #define RUBY_VERSION_TEENY 7
 #define RUBY_RELEASE_YEAR 2008
 #define RUBY_RELEASE_MONTH 12
-#define RUBY_RELEASE_DAY 12
+#define RUBY_RELEASE_DAY 13
 
 #ifdef RUBY_EXTERN
 RUBY_EXTERN const char ruby_version[];
@@ -25,7 +25,7 @@
 #define RUBY_BIRTH_MONTH 2
 #define RUBY_BIRTH_DAY 24
 
-#define RUBY_RELEASE_STR "MBARI 2 on patchlevel"
+#define RUBY_RELEASE_STR "MBARI 3 on patchlevel"
 #define RUBY_RELEASE_NUM RUBY_PATCHLEVEL
 
 
