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

ruby-changes:46471

From: normal <ko1@a...>
Date: Sun, 7 May 2017 13:26:43 +0900 (JST)
Subject: [ruby-changes:46471] normal:r58587 (trunk): variable.c: cleanup waitq upon thread death

normal	2017-05-07 13:26:37 +0900 (Sun, 07 May 2017)

  New Revision: 58587

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=58587

  Log:
    variable.c: cleanup waitq upon thread death
    
    * variable.c (autoload_reset): use idempotent list_del_init
      (autoload_sleep): moved code from rb_autoload_load
      (autoload_sleep_done): cleanup for use with rb_ensure
      (rb_autoload_load): ensure list delete happens in case the
      thread dies during sleep
    * test/ruby/bug-13526.rb: new script for separate execution
    * test/ruby/test_autoload.rb (test_bug_13526): new test
      [ruby-core:81016] [Bug #13526]

  Added files:
    trunk/test/ruby/bug-13526.rb
  Modified files:
    trunk/test/ruby/test_autoload.rb
    trunk/variable.c
Index: variable.c
===================================================================
--- variable.c	(revision 58586)
+++ variable.c	(revision 58587)
@@ -2095,7 +2095,7 @@ autoload_reset(VALUE arg) https://github.com/ruby/ruby/blob/trunk/variable.c#L2095
 	    VALUE th = cur->thread;
 
 	    cur->thread = Qfalse;
-	    list_del(&cur->waitq.node);
+	    list_del_init(&cur->waitq.node); /* idempotent */
 
 	    /*
 	     * cur is stored on the stack of cur->waiting_th,
@@ -2108,6 +2108,34 @@ autoload_reset(VALUE arg) https://github.com/ruby/ruby/blob/trunk/variable.c#L2108
     return 0;			/* ignored */
 }
 
+static VALUE
+autoload_sleep(VALUE arg)
+{
+    struct autoload_state *state = (struct autoload_state *)arg;
+
+    /*
+     * autoload_reset in other thread will resume us and remove us
+     * from the waitq list
+     */
+    do {
+	rb_thread_sleep_deadly();
+    } while (state->thread != Qfalse);
+
+    return Qfalse;
+}
+
+static VALUE
+autoload_sleep_done(VALUE arg)
+{
+    struct autoload_state *state = (struct autoload_state *)arg;
+
+    if (state->thread != Qfalse && rb_thread_to_be_killed(state->thread)) {
+	list_del_init(&state->waitq.node); /* idempotent */
+    }
+
+    return Qfalse;
+}
+
 VALUE
 rb_autoload_load(VALUE mod, ID id)
 {
@@ -2145,13 +2173,9 @@ rb_autoload_load(VALUE mod, ID id) https://github.com/ruby/ruby/blob/trunk/variable.c#L2173
     }
     else {
 	list_add_tail(&ele->state->waitq.head, &state.waitq.node);
-	/*
-	 * autoload_reset in other thread will resume us and remove us
-	 * from the waitq list
-	 */
-	do {
-	    rb_thread_sleep_deadly();
-	} while (state.thread != Qfalse);
+
+	rb_ensure(autoload_sleep, (VALUE)&state,
+		autoload_sleep_done, (VALUE)&state);
     }
 
     /* autoload_data_i can be deleted by another thread while require */
Index: test/ruby/test_autoload.rb
===================================================================
--- test/ruby/test_autoload.rb	(revision 58586)
+++ test/ruby/test_autoload.rb	(revision 58587)
@@ -241,6 +241,11 @@ p Foo::Bar https://github.com/ruby/ruby/blob/trunk/test/ruby/test_autoload.rb#L241
     end
   end
 
+  def test_bug_13526
+    script = File.join(__dir__, 'bug-13526.rb')
+    assert_ruby_status([script], '', '[ruby-core:81016] [Bug #13526]')
+  end
+
   def add_autoload(path)
     (@autoload_paths ||= []) << path
     ::Object.class_eval {autoload(:AutoloadTest, path)}
Index: test/ruby/bug-13526.rb
===================================================================
--- test/ruby/bug-13526.rb	(nonexistent)
+++ test/ruby/bug-13526.rb	(revision 58587)
@@ -0,0 +1,20 @@ https://github.com/ruby/ruby/blob/trunk/test/ruby/bug-13526.rb#L1
+# From https://bugs.ruby-lang.org/issues/13526#note-1
+
+sleep if $load
+$load = true
+
+n = 10
+threads = Array.new(n) do
+  Thread.new do
+    begin
+      autoload :Foo, "#{File.dirname($0)}/#{$0}"
+      Thread.pass
+      Foo
+    ensure
+      Thread.pass
+    end
+  end
+end
+
+Thread.pass while threads.all?(&:stop?)
+100.times { Thread.pass }

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

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