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

ruby-changes:45765

From: naruse <ko1@a...>
Date: Sat, 11 Mar 2017 22:02:06 +0900 (JST)
Subject: [ruby-changes:45765] naruse:r57838 (ruby_2_4): merge revision(s) 57199, 57202, 57206, 57224: [Backport #13076]

naruse	2017-03-11 22:02:01 +0900 (Sat, 11 Mar 2017)

  New Revision: 57838

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

  Log:
    merge revision(s) 57199,57202,57206,57224: [Backport #13076]
    
    io.c: fix race between read and close
    
    * io.c (io_fillbuf): fix race between read and close, in the case
      the IO gets closed before the reading thread achieve the lock.
      [ruby-core:78845] [Bug #13076]
    thread.c: fix race between read and close
    
    * thread.c (rb_thread_fd_close): wait until all threads using the
      fd finish the operation, not to free the buffer in use.
      [ruby-core:78845] [Bug #13076]
    revert a part of r57199
    
    * io.c (io_fillbuf): revert a part of r57199 because it broke IO#getch.
      see also [Bug #13076]
    
    io.c: fix race between read and close
    
    * io.c (io_fillbuf): fix race between read and close and bail out
      in the case the IO gets closed before the reading thread achieve
      the lock.  [ruby-core:78845] [Bug #13076]

  Modified directories:
    branches/ruby_2_4/
  Modified files:
    branches/ruby_2_4/io.c
    branches/ruby_2_4/test/ruby/test_io.rb
    branches/ruby_2_4/thread.c
    branches/ruby_2_4/version.h
Index: ruby_2_4/version.h
===================================================================
--- ruby_2_4/version.h	(revision 57837)
+++ ruby_2_4/version.h	(revision 57838)
@@ -1,6 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_4/version.h#L1
 #define RUBY_VERSION "2.4.0"
 #define RUBY_RELEASE_DATE "2017-03-11"
-#define RUBY_PATCHLEVEL 6
+#define RUBY_PATCHLEVEL 7
 
 #define RUBY_RELEASE_YEAR 2017
 #define RUBY_RELEASE_MONTH 3
Index: ruby_2_4/io.c
===================================================================
--- ruby_2_4/io.c	(revision 57837)
+++ ruby_2_4/io.c	(revision 57838)
@@ -424,7 +424,7 @@ rb_cloexec_fcntl_dupfd(int fd, int minfd https://github.com/ruby/ruby/blob/trunk/ruby_2_4/io.c#L424
     if (!READ_DATA_PENDING(fptr)) {\
 	WAIT_FD_IN_WIN32(fptr);\
 	rb_io_check_closed(fptr);\
-     }\
+    }\
 } while(0)
 
 #ifndef S_ISSOCK
@@ -1775,6 +1775,7 @@ io_fillbuf(rb_io_t *fptr) https://github.com/ruby/ruby/blob/trunk/ruby_2_4/io.c#L1775
 		rb_syserr_fail_path(e, path);
 	    }
         }
+	if (r > 0) rb_io_check_closed(fptr);
         fptr->rbuf.off = 0;
         fptr->rbuf.len = (int)r; /* r should be <= rbuf_capa */
         if (r == 0)
Index: ruby_2_4/thread.c
===================================================================
--- ruby_2_4/thread.c	(revision 57837)
+++ ruby_2_4/thread.c	(revision 57838)
@@ -2164,14 +2164,22 @@ rb_thread_fd_close(int fd) https://github.com/ruby/ruby/blob/trunk/ruby_2_4/thread.c#L2164
 {
     rb_vm_t *vm = GET_THREAD()->vm;
     rb_thread_t *th = 0;
+    int busy;
 
+  retry:
+    busy = 0;
     list_for_each(&vm->living_threads, th, vmlt_node) {
 	if (th->waiting_fd == fd) {
 	    VALUE err = th->vm->special_exceptions[ruby_error_closed_stream];
 	    rb_threadptr_pending_interrupt_enque(th, err);
 	    rb_threadptr_interrupt(th);
+	    busy = 1;
 	}
     }
+    if (busy) {
+	rb_thread_schedule_limits(0);
+	goto retry;
+    }
 }
 
 /*
Index: ruby_2_4/test/ruby/test_io.rb
===================================================================
--- ruby_2_4/test/ruby/test_io.rb	(revision 57837)
+++ ruby_2_4/test/ruby/test_io.rb	(revision 57838)
@@ -3366,6 +3366,36 @@ __END__ https://github.com/ruby/ruby/blob/trunk/ruby_2_4/test/ruby/test_io.rb#L3366
     end
   end if File::BINARY != 0
 
+  def test_race_gets_and_close
+    assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}")
+    bug13076 = '[ruby-core:78845] [Bug #13076]'
+    begin;
+      100.times do |i|
+        a = []
+        t = []
+        10.times do
+          r,w = IO.pipe
+          a << [r,w]
+          t << Thread.new do
+            begin
+              while r.gets
+              end
+            rescue IOError
+            end
+          end
+        end
+        a.each do |r,w|
+          w.puts "hoge"
+          w.close
+          r.close
+        end
+        assert_nothing_raised(IOError, bug13076) {
+          t.each(&:join)
+        }
+      end
+    end;
+  end
+
   if RUBY_ENGINE == "ruby" # implementation details
     def test_foreach_rs_conversion
       make_tempfile {|t|

Property changes on: ruby_2_4
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /trunk:r57199,57202,57206,57224


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

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