[前][次][番号順一覧][スレッド一覧]

ruby-changes:10961

From: shyouhei <ko1@a...>
Date: Sun, 22 Feb 2009 22:03:32 +0900 (JST)
Subject: [ruby-changes:10961] Ruby:r22538 (ruby_1_8_6): merge revision(s) 21353:

shyouhei	2009-02-22 22:01:37 +0900 (Sun, 22 Feb 2009)

  New Revision: 22538

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=22538

  Log:
    merge revision(s) 21353:
    * eval.c (cc_mark): frees the continuation's stack if its thread
      is dead to avoid recursive gc that segfaults.  [ruby-core:13889]
      a patch by Brent Roman <brent AT mbari.org>.
    * eval.c (rb_cont_check): checks for valid continuation instance.
    * eval.c (rb_callcc): assigns th->thread before scope_dup() to
      avoid segfaults if this scope_dup() triggers a gc pass.
      a patch by Brent Roman <brent AT mbari.org>.

  Modified files:
    branches/ruby_1_8_6/ChangeLog
    branches/ruby_1_8_6/eval.c
    branches/ruby_1_8_6/version.h

Index: ruby_1_8_6/ChangeLog
===================================================================
--- ruby_1_8_6/ChangeLog	(revision 22537)
+++ ruby_1_8_6/ChangeLog	(revision 22538)
@@ -1,3 +1,15 @@
+Sun Feb 22 21:50:29 2009  Nobuyoshi Nakada  <nobu@r...>
+
+	* eval.c (cc_mark): frees the continuation's stack if its thread
+	  is dead to avoid recursive gc that segfaults.  [ruby-core:13889]
+	  a patch by Brent Roman <brent AT mbari.org>.
+
+	* eval.c (rb_cont_check): checks for valid continuation instance.
+
+	* eval.c (rb_callcc): assigns th->thread before scope_dup() to
+	  avoid segfaults if this scope_dup() triggers a gc pass.
+	  a patch by Brent Roman <brent AT mbari.org>.
+
 Sun Feb 22 00:29:05 2009  Nobuyoshi Nakada  <nobu@r...>
 
 	* ext/extmk.rb (extmake): does not use both of makefile.rb and
Index: ruby_1_8_6/version.h
===================================================================
--- ruby_1_8_6/version.h	(revision 22537)
+++ ruby_1_8_6/version.h	(revision 22538)
@@ -2,7 +2,7 @@
 #define RUBY_RELEASE_DATE "2009-02-22"
 #define RUBY_VERSION_CODE 186
 #define RUBY_RELEASE_CODE 20090222
-#define RUBY_PATCHLEVEL 349
+#define RUBY_PATCHLEVEL 350
 
 #define RUBY_VERSION_MAJOR 1
 #define RUBY_VERSION_MINOR 8
Index: ruby_1_8_6/eval.c
===================================================================
--- ruby_1_8_6/eval.c	(revision 22537)
+++ ruby_1_8_6/eval.c	(revision 22538)
@@ -10230,8 +10230,8 @@
     } END_FOREACH_FROM(main_thread, th);
 }
 
-static void
-thread_free(th)
+static inline void
+stack_free(th)
     rb_thread_t th;
 {
     if (th->stk_ptr) free(th->stk_ptr);
@@ -10240,6 +10240,13 @@
     if (th->bstr_ptr) free(th->bstr_ptr);
     th->bstr_ptr = 0;
 #endif
+}
+
+static void
+thread_free(th)
+    rb_thread_t th;
+{
+    stack_free(th);
     if (th->locals) st_free_table(th->locals);
     if (th->status != THREAD_KILLED) {
 	if (th->prev) th->prev->next = th->next;
@@ -10532,8 +10539,7 @@
 {
     th->thgroup = 0;
     th->status = THREAD_KILLED;
-    if (th->stk_ptr) free(th->stk_ptr);
-    th->stk_ptr = 0;
+    stack_free(th);
 }
 
 static void
@@ -12776,6 +12782,38 @@
 }
 
 
+static void
+cc_purge(cc)
+    rb_thread_t cc;
+{
+    /* free continuation's stack if it has just died */
+    if (NIL_P(cc->thread)) return;
+    if (rb_thread_check(cc->thread)->status == THREAD_KILLED) {
+	cc->thread = Qnil;
+	rb_thread_die(cc);  /* can't possibly activate this stack */
+    }
+}
+
+static void
+cc_mark(cc)
+    rb_thread_t cc;
+{
+    /* mark this continuation's stack only if its parent thread is still alive */
+    cc_purge(cc);
+    thread_mark(cc);
+}
+
+static rb_thread_t
+rb_cont_check(data)
+    VALUE data;
+{
+    if (TYPE(data) != T_DATA || RDATA(data)->dmark != (RUBY_DATA_FUNC)cc_mark) {
+	rb_raise(rb_eTypeError, "wrong argument type %s (expected Continuation)",
+		 rb_obj_classname(data));
+    }
+    return (rb_thread_t)RDATA(data)->data;
+}
+
 /*
  *  Document-class: Continuation
  *
@@ -12850,14 +12888,16 @@
     struct RVarmap *vars;
 
     THREAD_ALLOC(th);
-    cont = Data_Wrap_Struct(rb_cCont, thread_mark, thread_free, th);
+    /* must finish th initialization before any possible gc.
+     * brent@m... */
+    th->thread = curr_thread->thread;
+    th->thgroup = cont_protect;
+    cont = Data_Wrap_Struct(rb_cCont, cc_mark, thread_free, th);
 
     scope_dup(ruby_scope);
     for (tag=prot_tag; tag; tag=tag->prev) {
 	scope_dup(tag->scope);
     }
-    th->thread = curr_thread->thread;
-    th->thgroup = cont_protect;
 
     for (vars = ruby_dyna_vars; vars; vars = vars->next) {
 	if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
@@ -12894,7 +12934,7 @@
     VALUE *argv;
     VALUE cont;
 {
-    rb_thread_t th = rb_thread_check(cont);
+    rb_thread_t th = rb_cont_check(cont);
 
     if (th->thread != curr_thread->thread) {
 	rb_raise(rb_eRuntimeError, "continuation called across threads");
@@ -13070,10 +13110,6 @@
 
     rb_secure(4);
     th = rb_thread_check(thread);
-    if (!th->next || !th->prev) {
-	rb_raise(rb_eTypeError, "wrong argument type %s (expected Thread)",
-		 rb_obj_classname(thread));
-    }
 
     if (OBJ_FROZEN(group)) {
       rb_raise(rb_eThreadError, "can't move to the frozen thread group");

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]