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

ruby-changes:19688

From: shyouhei <ko1@a...>
Date: Wed, 25 May 2011 14:38:06 +0900 (JST)
Subject: [ruby-changes:19688] shyouhei:r31732 (ruby_1_8): * variable.c (rb_autoload_load): There is a race condition while

shyouhei	2011-05-25 14:36:31 +0900 (Wed, 25 May 2011)

  New Revision: 31732

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

  Log:
    * variable.c (rb_autoload_load):  There is a  race condition while
      autoloading.  When two or more threads touch a single autoloaded
      constant at  a time,  one of them  does the require,  but others
      behave  oddly.   To  fix  this  situation we  now  refrain  from
      deleting the autoload table while someone is doing the autoload.
      That  deletion is  deferred to  a  point where  a require  ended
      successfully.  Doing so make it possible for multiple threads to
      enter autoloading at the same  time but the require is protected
      against  multiple simultaneous  entrance anyway  so all  but one
      thread  gets blocked  at that  point.   So with  it, touching  a
      constant that gets autoloaded cause those threads to block until
      there is another one that does the same thing.
      [ruby-core:36308] (#921)
    
    * variable.c (rb_const_get_0): ditto.
    
    * variable.c (autoload_node): ditto.
    
    * variable.c (autoload_delete): ditto.

  Modified files:
    branches/ruby_1_8/ChangeLog
    branches/ruby_1_8/variable.c

Index: ruby_1_8/ChangeLog
===================================================================
--- ruby_1_8/ChangeLog	(revision 31731)
+++ ruby_1_8/ChangeLog	(revision 31732)
@@ -1,3 +1,25 @@
+Wed May 25 14:35:02 2011  URABE Shyouhei  <shyouhei@r...>
+
+	* variable.c (rb_autoload_load):  There is a  race condition while
+	  autoloading.  When two or more threads touch a single autoloaded
+	  constant at  a time,  one of them  does the require,  but others
+	  behave  oddly.   To  fix  this  situation we  now  refrain  from
+	  deleting the autoload table while someone is doing the autoload.
+	  That  deletion is  deferred to  a  point where  a require  ended
+	  successfully.  Doing so make it possible for multiple threads to
+	  enter autoloading at the same  time but the require is protected
+	  against  multiple simultaneous  entrance anyway  so all  but one
+	  thread  gets blocked  at that  point.   So with  it, touching  a
+	  constant that gets autoloaded cause those threads to block until
+	  there is another one that does the same thing.
+	  [ruby-core:36308] (#921)
+
+	* variable.c (rb_const_get_0): ditto.
+
+	* variable.c (autoload_node): ditto.
+
+	* variable.c (autoload_delete): ditto.
+
 Sat May 21 07:33:54 2011  Yusuke Endoh  <mame@t...>
 
 	* ext/zlib/zlib.c (zstream_append_input2): add RB_GC_GUARD.
Index: ruby_1_8/variable.c
===================================================================
--- ruby_1_8/variable.c	(revision 31731)
+++ ruby_1_8/variable.c	(revision 31732)
@@ -1333,7 +1333,6 @@
 {
     st_data_t val, load = 0, n = id;
 
-    st_delete(RCLASS(mod)->iv_tbl, &n, 0);
     if (st_lookup(RCLASS(mod)->iv_tbl, autoload, &val)) {
 	struct st_table *tbl = check_autoload_table((VALUE)val);
 
@@ -1347,18 +1346,38 @@
     return (NODE *)load;
 }
 
+static NODE *
+autoload_node(mod, id)
+    VALUE mod;
+    ID id;
+{
+    st_data_t val, load, n = id;
+    struct st_table *p = RCLASS(mod)->iv_tbl;
+
+    if (p && st_lookup(p, autoload, &val)) {
+        st_table *q = check_autoload_table((VALUE)val);
+
+        if (q && st_lookup(q, n, &load)) {
+            return (NODE *)load;
+        }
+    }
+    return 0;
+}
+
 VALUE
 rb_autoload_load(klass, id)
     VALUE klass;
     ID id;
 {
-    VALUE file;
-    NODE *load = autoload_delete(klass, id);
+    NODE *load = 0;
+    VALUE ret = 0;
 
-    if (!load || !(file = load->nd_lit) || rb_provided(RSTRING(file)->ptr)) {
-	return Qfalse;
+    if ((load = autoload_node(klass, id)) != 0) {
+        if ((ret = rb_require_safe(load->nd_lit, load->nd_nth)) != Qfalse) {
+            (void) autoload_delete(klass, id);
+        }
     }
-    return rb_require_safe(file, load->nd_nth);
+    return ret;
 }
 
 static VALUE
@@ -1420,7 +1439,7 @@
     while (tmp) {
 	while (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) {
 	    if (value == Qundef) {
-		if (!RTEST(rb_autoload_load(tmp, id))) break;
+		rb_autoload_load(tmp, id);
 		continue;
 	    }
 	    if (exclude && tmp == rb_cObject && klass != rb_cObject) {

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

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