603d5bc
Index: ruby_1_8_7/marshal.c
603d5bc
===================================================================
603d5bc
--- ruby_1_8_7/marshal.c	(revision 26075)
603d5bc
+++ ruby_1_8_7/marshal.c	(revision 26076)
603d5bc
@@ -85,12 +85,10 @@
603d5bc
 static ID s_getc, s_read, s_write, s_binmode;
603d5bc
 
603d5bc
 struct dump_arg {
603d5bc
-    VALUE obj;
603d5bc
     VALUE str, dest;
603d5bc
     st_table *symbols;
603d5bc
     st_table *data;
603d5bc
     int taint;
603d5bc
-    VALUE wrapper;
603d5bc
 };
603d5bc
 
603d5bc
 struct dump_call_arg {
603d5bc
@@ -104,22 +102,32 @@
603d5bc
     struct dump_arg *arg;
603d5bc
     ID sym;
603d5bc
 {
603d5bc
-    if (!DATA_PTR(arg->wrapper)) {
603d5bc
+    if (!arg->symbols) {
603d5bc
         rb_raise(rb_eRuntimeError, "Marshal.dump reentered at %s",
603d5bc
 		 rb_id2name(sym));
603d5bc
     }
603d5bc
 }
603d5bc
 
603d5bc
+static void clear_dump_arg _((struct dump_arg *arg));
603d5bc
+
603d5bc
 static void
603d5bc
 mark_dump_arg(ptr)
603d5bc
     void *ptr;
603d5bc
 {
603d5bc
     struct dump_arg *p = ptr;
603d5bc
-    if (!ptr)
603d5bc
+    if (!p->symbols)
603d5bc
         return;
603d5bc
     rb_mark_set(p->data);
603d5bc
 }
603d5bc
 
603d5bc
+static void
603d5bc
+free_dump_arg(ptr)
603d5bc
+    void *ptr;
603d5bc
+{
603d5bc
+    clear_dump_arg(ptr);
603d5bc
+    xfree(ptr);
603d5bc
+}
603d5bc
+
603d5bc
 static VALUE
603d5bc
 class2path(klass)
603d5bc
     VALUE klass;
603d5bc
@@ -699,32 +707,17 @@
603d5bc
     }
603d5bc
 }
603d5bc
 
603d5bc
-static VALUE
603d5bc
-dump(arg)
603d5bc
-    struct dump_call_arg *arg;
603d5bc
-{
603d5bc
-    w_object(arg->obj, arg->arg, arg->limit);
603d5bc
-    if (arg->arg->dest) {
603d5bc
-	rb_io_write(arg->arg->dest, arg->arg->str);
603d5bc
-	rb_str_resize(arg->arg->str, 0);
603d5bc
-    }
603d5bc
-    return 0;
603d5bc
-}
603d5bc
-
603d5bc
-static VALUE
603d5bc
-dump_ensure(arg)
603d5bc
+static void
603d5bc
+clear_dump_arg(arg)
603d5bc
     struct dump_arg *arg;
603d5bc
 {
603d5bc
-    if (!DATA_PTR(arg->wrapper)) return 0;
603d5bc
+    if (!arg->symbols) return;
603d5bc
     st_free_table(arg->symbols);
603d5bc
+    arg->symbols = 0;
603d5bc
     st_free_table(arg->data);
603d5bc
-    DATA_PTR(arg->wrapper) = 0;
603d5bc
-    arg->wrapper = 0;
603d5bc
     if (arg->taint) {
603d5bc
 	OBJ_TAINT(arg->str);
603d5bc
     }
603d5bc
-
603d5bc
-    return 0;
603d5bc
 }
603d5bc
 
603d5bc
 /*
603d5bc
@@ -760,8 +753,8 @@
603d5bc
 {
603d5bc
     VALUE obj, port, a1, a2;
603d5bc
     int limit = -1;
603d5bc
-    struct dump_arg arg;
603d5bc
-    struct dump_call_arg c_arg;
603d5bc
+    struct dump_arg *arg;
603d5bc
+    VALUE wrapper;
603d5bc
 
603d5bc
     port = Qnil;
603d5bc
     rb_scan_args(argc, argv, "12", &obj, &a1, &a2;;
603d5bc
@@ -775,37 +768,40 @@
603d5bc
 	else if (NIL_P(a1)) goto type_error;
603d5bc
 	else port = a1;
603d5bc
     }
603d5bc
-    arg.dest = 0;
603d5bc
-    arg.symbols = st_init_numtable();
603d5bc
-    arg.data    = st_init_numtable();
603d5bc
-    arg.taint   = Qfalse;
603d5bc
-    arg.str = rb_str_buf_new(0);
603d5bc
-    RBASIC(arg.str)->klass = 0;
603d5bc
-    arg.wrapper = Data_Wrap_Struct(rb_cData, mark_dump_arg, 0, &arg;;
603d5bc
+    wrapper = Data_Make_Struct(rb_cData, struct dump_arg, mark_dump_arg, free_dump_arg, arg);
603d5bc
+    arg->dest = 0;
603d5bc
+    arg->symbols = st_init_numtable();
603d5bc
+    arg->data    = st_init_numtable();
603d5bc
+    arg->taint   = Qfalse;
603d5bc
+    arg->str = rb_str_buf_new(0);
603d5bc
+    RBASIC(arg->str)->klass = 0;
603d5bc
     if (!NIL_P(port)) {
603d5bc
 	if (!rb_respond_to(port, s_write)) {
603d5bc
 	  type_error:
603d5bc
 	    rb_raise(rb_eTypeError, "instance of IO needed");
603d5bc
 	}
603d5bc
-	arg.dest = port;
603d5bc
+	arg->dest = port;
603d5bc
 	if (rb_respond_to(port, s_binmode)) {
603d5bc
 	    rb_funcall2(port, s_binmode, 0, 0);
603d5bc
-	    check_dump_arg(&arg, s_binmode);
603d5bc
+	    check_dump_arg(arg, s_binmode);
603d5bc
 	}
603d5bc
     }
603d5bc
     else {
603d5bc
-	port = arg.str;
603d5bc
+	port = arg->str;
603d5bc
     }
603d5bc
 
603d5bc
-    c_arg.obj   = obj;
603d5bc
-    c_arg.arg   = &arg;
603d5bc
-    c_arg.limit = limit;
603d5bc
+    w_byte(MARSHAL_MAJOR, arg);
603d5bc
+    w_byte(MARSHAL_MINOR, arg);
603d5bc
 
603d5bc
-    w_byte(MARSHAL_MAJOR, &arg;;
603d5bc
-    w_byte(MARSHAL_MINOR, &arg;;
603d5bc
+    w_object(obj, arg, limit);
603d5bc
+    if (arg->dest) {
603d5bc
+	rb_io_write(arg->dest, arg->str);
603d5bc
+	rb_str_resize(arg->str, 0);
603d5bc
+    }
603d5bc
 
603d5bc
-    rb_ensure(dump, (VALUE)&c_arg, dump_ensure, (VALUE)&arg;;
603d5bc
-    RBASIC(arg.str)->klass = rb_cString;
603d5bc
+    RBASIC(arg->str)->klass = rb_cString;
603d5bc
+    clear_dump_arg(arg);
603d5bc
+    RB_GC_GUARD(wrapper);
603d5bc
 
603d5bc
     return port;
603d5bc
 }
603d5bc
@@ -817,7 +813,6 @@
603d5bc
     st_table *data;
603d5bc
     VALUE proc;
603d5bc
     int taint;
603d5bc
-    VALUE wrapper;
603d5bc
 };
603d5bc
 
603d5bc
 static void
603d5bc
@@ -825,22 +820,31 @@
603d5bc
     struct load_arg *arg;
603d5bc
     ID sym;
603d5bc
 {
603d5bc
-    if (!DATA_PTR(arg->wrapper)) {
603d5bc
+    if (!arg->symbols) {
603d5bc
         rb_raise(rb_eRuntimeError, "Marshal.load reentered at %s",
603d5bc
 		 rb_id2name(sym));
603d5bc
     }
603d5bc
 }
603d5bc
 
603d5bc
+static void clear_load_arg _((struct load_arg *arg));
603d5bc
+
603d5bc
 static void
603d5bc
 mark_load_arg(ptr)
603d5bc
     void *ptr;
603d5bc
 {
603d5bc
     struct load_arg *p = ptr;
603d5bc
-    if (!ptr)
603d5bc
+    if (!p->symbols)
603d5bc
         return;
603d5bc
     rb_mark_tbl(p->data);
603d5bc
 }
603d5bc
 
603d5bc
+static void
603d5bc
+free_load_arg(void *ptr)
603d5bc
+{
603d5bc
+    clear_load_arg(ptr);
603d5bc
+    xfree(ptr);
603d5bc
+}
603d5bc
+
603d5bc
 static VALUE r_object _((struct load_arg *arg));
603d5bc
 
603d5bc
 static int
603d5bc
@@ -1415,23 +1419,14 @@
603d5bc
     return r_object0(arg, arg->proc, 0, Qnil);
603d5bc
 }
603d5bc
 
603d5bc
-static VALUE
603d5bc
-load(arg)
603d5bc
+static void
603d5bc
+clear_load_arg(arg)
603d5bc
     struct load_arg *arg;
603d5bc
 {
603d5bc
-    return r_object(arg);
603d5bc
-}
603d5bc
-
603d5bc
-static VALUE
603d5bc
-load_ensure(arg)
603d5bc
-    struct load_arg *arg;
603d5bc
-{
603d5bc
-    if (!DATA_PTR(arg->wrapper)) return 0;
603d5bc
+    if (!arg->symbols) return;
603d5bc
     st_free_table(arg->symbols);
603d5bc
+    arg->symbols = 0;
603d5bc
     st_free_table(arg->data);
603d5bc
-    DATA_PTR(arg->wrapper) = 0;
603d5bc
-    arg->wrapper = 0;
603d5bc
-    return 0;
603d5bc
 }
603d5bc
 
603d5bc
 /*
603d5bc
@@ -1451,35 +1446,37 @@
603d5bc
     VALUE *argv;
603d5bc
 {
603d5bc
     VALUE port, proc;
603d5bc
-    int major, minor;
603d5bc
-    VALUE v;
603d5bc
-    struct load_arg arg;
603d5bc
+    int major, minor, taint = Qfalse;
603d5bc
+    VALUE v, wrapper;
603d5bc
+    struct load_arg *arg;
603d5bc
 
603d5bc
     rb_scan_args(argc, argv, "11", &port, &proc;;
603d5bc
     v = rb_check_string_type(port);
603d5bc
     if (!NIL_P(v)) {
603d5bc
-	arg.taint = OBJ_TAINTED(port); /* original taintedness */
603d5bc
+	taint = OBJ_TAINTED(port); /* original taintedness */
603d5bc
 	port = v;
603d5bc
     }
603d5bc
     else if (rb_respond_to(port, s_getc) && rb_respond_to(port, s_read)) {
603d5bc
 	if (rb_respond_to(port, s_binmode)) {
603d5bc
 	    rb_funcall2(port, s_binmode, 0, 0);
603d5bc
 	}
603d5bc
-	arg.taint = Qtrue;
603d5bc
+	taint = Qtrue;
603d5bc
     }
603d5bc
     else {
603d5bc
 	rb_raise(rb_eTypeError, "instance of IO needed");
603d5bc
     }
603d5bc
-    arg.src = port;
603d5bc
-    arg.offset = 0;
603d5bc
-    arg.symbols = st_init_numtable();
603d5bc
-    arg.data    = st_init_numtable();
603d5bc
-    arg.proc = 0;
603d5bc
-    arg.wrapper = Data_Wrap_Struct(rb_cData, mark_load_arg, 0, &arg;;
603d5bc
+    wrapper = Data_Make_Struct(rb_cData, struct load_arg, mark_load_arg, free_load_arg, arg);
603d5bc
+    arg->src = port;
603d5bc
+    arg->offset = 0;
603d5bc
+    arg->symbols = st_init_numtable();
603d5bc
+    arg->data    = st_init_numtable();
603d5bc
+    arg->proc = 0;
603d5bc
+    arg->taint = taint;
603d5bc
 
603d5bc
-    major = r_byte(&arg;;
603d5bc
-    minor = r_byte(&arg;;
603d5bc
+    major = r_byte(arg);
603d5bc
+    minor = r_byte(arg);
603d5bc
     if (major != MARSHAL_MAJOR || minor > MARSHAL_MINOR) {
603d5bc
+	clear_load_arg(arg);
603d5bc
 	rb_raise(rb_eTypeError, "incompatible marshal file format (can't be read)\n\
603d5bc
 \tformat version %d.%d required; %d.%d given",
603d5bc
 		 MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
603d5bc
@@ -1490,8 +1487,10 @@
603d5bc
 		MARSHAL_MAJOR, MARSHAL_MINOR, major, minor);
603d5bc
     }
603d5bc
 
603d5bc
-    if (!NIL_P(proc)) arg.proc = proc;
603d5bc
-    v = rb_ensure(load, (VALUE)&arg, load_ensure, (VALUE)&arg;;
603d5bc
+    if (!NIL_P(proc)) arg->proc = proc;
603d5bc
+    v = r_object(arg);
603d5bc
+    clear_load_arg(arg);
603d5bc
+    RB_GC_GUARD(wrapper);
603d5bc
 
603d5bc
     return v;
603d5bc
 }
603d5bc
Index: ruby_1_8_7/test/ruby/test_marshal.rb
603d5bc
===================================================================
603d5bc
--- ruby_1_8_7/test/ruby/test_marshal.rb	(revision 26075)
603d5bc
+++ ruby_1_8_7/test/ruby/test_marshal.rb	(revision 26076)
603d5bc
@@ -71,4 +71,41 @@
603d5bc
     }
603d5bc
     assert_equal("marshal data too short", e.message)
603d5bc
   end
603d5bc
+
603d5bc
+  class DumpTest
603d5bc
+    def marshal_dump
603d5bc
+      loop { Thread.pass }
603d5bc
+    end
603d5bc
+  end
603d5bc
+
603d5bc
+  class LoadTest
603d5bc
+    def marshal_dump
603d5bc
+      nil
603d5bc
+    end
603d5bc
+    def marshal_load(obj)
603d5bc
+      loop { Thread.pass }
603d5bc
+    end
603d5bc
+  end
603d5bc
+
603d5bc
+  def test_context_switch
603d5bc
+    o = DumpTest.new
603d5bc
+    Thread.new { Marshal.dump(o) }
603d5bc
+    GC.start
603d5bc
+    assert(true, '[ruby-dev:39425]')
603d5bc
+
603d5bc
+    o = LoadTest.new
603d5bc
+    m = Marshal.dump(o)
603d5bc
+    Thread.new { Marshal.load(m) }
603d5bc
+    GC.start
603d5bc
+    assert(true, '[ruby-dev:39425]')
603d5bc
+  end
603d5bc
+
603d5bc
+  def test_taint
603d5bc
+    x = Object.new
603d5bc
+    x.taint
603d5bc
+    s = Marshal.dump(x)
603d5bc
+    assert_equal(true, s.tainted?)
603d5bc
+    y = Marshal.load(s)
603d5bc
+    assert_equal(true, y.tainted?)
603d5bc
+  end
603d5bc
 end
603d5bc
Index: ruby_1_8_7/ruby.h
603d5bc
===================================================================
603d5bc
--- ruby_1_8_7/ruby.h	(revision 16014)
603d5bc
+++ ruby_1_8_7/ruby.h	(revision 16015)
603d5bc
@@ -224,6 +224,8 @@
603d5bc
 
603d5bc
 #define TYPE(x) rb_type((VALUE)(x))
603d5bc
 
603d5bc
+#define RB_GC_GUARD(v) (*(volatile VALUE *)&(v))
603d5bc
+
603d5bc
 void rb_check_type _((VALUE,int));
603d5bc
 #define Check_Type(v,t) rb_check_type((VALUE)(v),t)
603d5bc