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

ruby-changes:46914

From: normal <ko1@a...>
Date: Wed, 7 Jun 2017 07:55:43 +0900 (JST)
Subject: [ruby-changes:46914] normal:r59028 (trunk): IO#close: do not enqueue redundant interrupts (take #2)

normal	2017-06-07 07:55:35 +0900 (Wed, 07 Jun 2017)

  New Revision: 59028

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

  Log:
    IO#close: do not enqueue redundant interrupts (take #2)
    
    Enqueuing multiple errors for one event causes spurious errors
    down the line, as reported by Nikolay Vashchenko in
    https://bugs.ruby-lang.org/issues/13632
    
    This should fix bad interactions with test_race_gets_and_close
    in test/ruby/test_io.rb since we ensure rb_notify_fd_close
    continues returning the busy flag after enqueuing the interrupt.
    
    Backporting changes to 2.4 and earlier releases will be more
    challenging...
    
    * thread.c (rb_notify_fd_close): do not enqueue multiple interrupts
      [ruby-core:81581] [Bug #13632]
    * test/ruby/test_io.rb (test_single_exception_on_close):
      new test based on script from Nikolay

  Modified files:
    trunk/test/ruby/test_io.rb
    trunk/thread.c
Index: test/ruby/test_io.rb
===================================================================
--- test/ruby/test_io.rb	(revision 59027)
+++ test/ruby/test_io.rb	(revision 59028)
@@ -2823,6 +2823,28 @@ __END__ https://github.com/ruby/ruby/blob/trunk/test/ruby/test_io.rb#L2823
     end;
   end
 
+  def test_single_exception_on_close
+    a = []
+    t = []
+    10.times do
+      r, w = IO.pipe
+      a << [r, w]
+      t << Thread.new do
+        while r.gets
+        end rescue IOError
+        Thread.current.pending_interrupt?
+      end
+    end
+    a.each do |r, w|
+      w.write -"\n"
+      w.close
+      r.close
+    end
+    t.each do |th|
+      assert_equal false, th.value, '[ruby-core:81581] [Bug #13632]'
+    end
+  end
+
   def test_open_mode
     feature4742 = "[ruby-core:36338]"
     bug6055 = '[ruby-dev:45268]'
Index: thread.c
===================================================================
--- thread.c	(revision 59027)
+++ thread.c	(revision 59028)
@@ -2212,10 +2212,16 @@ rb_notify_fd_close(int fd) https://github.com/ruby/ruby/blob/trunk/thread.c#L2212
     list_for_each(&vm->waiting_fds, wfd, wfd_node) {
 	if (wfd->fd == fd) {
 	    rb_thread_t *th = wfd->th;
-	    VALUE err = th->vm->special_exceptions[ruby_error_stream_closed];
+	    VALUE err;
+
+	    busy = 1;
+	    if (!th) {
+		continue;
+	    }
+	    wfd->th = 0;
+	    err = th->vm->special_exceptions[ruby_error_stream_closed];
 	    rb_threadptr_pending_interrupt_enque(th, err);
 	    rb_threadptr_interrupt(th);
-	    busy = 1;
 	}
     }
     return busy;

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

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