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

ruby-changes:31065

From: nagachika <ko1@a...>
Date: Sat, 5 Oct 2013 02:31:01 +0900 (JST)
Subject: [ruby-changes:31065] nagachika:r43144 (ruby_2_0_0): merge revision(s) 43112, 43114, 43117, 43118: [Backport #8980]

nagachika	2013-10-05 02:30:50 +0900 (Sat, 05 Oct 2013)

  New Revision: 43144

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

  Log:
    merge revision(s) 43112,43114,43117,43118: [Backport #8980]
    
    * io.c (rb_io_close_read): keep fptr in write_io to be discarded, to
      fix freed pointer access when it is in use by other threads, and get
      rid of potential memory/fd leak.
    
    * io.c (rb_io_close_write): detach tied IO for writing before closing
      to get rid of race condition.  [ruby-list:49598]
    
    * io.c (rb_io_close_read): duplex IO should wait its child process
      even after close_read.

  Modified directories:
    branches/ruby_2_0_0/
  Modified files:
    branches/ruby_2_0_0/ChangeLog
    branches/ruby_2_0_0/io.c
    branches/ruby_2_0_0/test/ruby/test_io.rb
    branches/ruby_2_0_0/version.h
Index: ruby_2_0_0/ChangeLog
===================================================================
--- ruby_2_0_0/ChangeLog	(revision 43143)
+++ ruby_2_0_0/ChangeLog	(revision 43144)
@@ -1,3 +1,14 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ChangeLog#L1
+Sat Oct  5 02:14:56 2013  Nobuyoshi Nakada  <nobu@r...>
+
+	* io.c (rb_io_close_read): duplex IO should wait its child process
+	  even after close_read.
+
+Sat Oct  5 02:14:56 2013  Nobuyoshi Nakada  <nobu@r...>
+
+	* io.c (rb_io_close_read): keep fptr in write_io to be discarded, to
+	  fix freed pointer access when it is in use by other threads, and get
+	  rid of potential memory/fd leak.
+
 Sat Oct  5 01:59:50 2013  Shugo Maeda  <shugo@r...>
 
 	* vm_method.c (rb_undef): raise a NameError if the original method
Index: ruby_2_0_0/io.c
===================================================================
--- ruby_2_0_0/io.c	(revision 43143)
+++ ruby_2_0_0/io.c	(revision 43144)
@@ -4369,11 +4369,16 @@ rb_io_close_read(VALUE io) https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/io.c#L4369
     write_io = GetWriteIO(io);
     if (io != write_io) {
 	rb_io_t *wfptr;
-        rb_io_fptr_cleanup(fptr, FALSE);
 	GetOpenFile(write_io, wfptr);
+	wfptr->pid = fptr->pid;
+	fptr->pid = 0;
         RFILE(io)->fptr = wfptr;
-        RFILE(write_io)->fptr = NULL;
-        rb_io_fptr_finalize(fptr);
+	/* bind to write_io temporarily to get rid of memory/fd leak */
+	fptr->tied_io_for_writing = 0;
+	fptr->mode &= ~FMODE_DUPLEX;
+	RFILE(write_io)->fptr = fptr;
+	rb_io_fptr_cleanup(fptr, FALSE);
+	/* should not finalize fptr because another thread may be reading it */
         return Qnil;
     }
 
@@ -4429,12 +4434,12 @@ rb_io_close_write(VALUE io) https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/io.c#L4434
 	rb_raise(rb_eIOError, "closing non-duplex IO for writing");
     }
 
-    rb_io_close(write_io);
     if (io != write_io) {
 	GetOpenFile(io, fptr);
 	fptr->tied_io_for_writing = 0;
 	fptr->mode &= ~FMODE_DUPLEX;
     }
+    rb_io_close(write_io);
     return Qnil;
 }
 
Index: ruby_2_0_0/version.h
===================================================================
--- ruby_2_0_0/version.h	(revision 43143)
+++ ruby_2_0_0/version.h	(revision 43144)
@@ -1,6 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/version.h#L1
 #define RUBY_VERSION "2.0.0"
 #define RUBY_RELEASE_DATE "2013-10-05"
-#define RUBY_PATCHLEVEL 325
+#define RUBY_PATCHLEVEL 326
 
 #define RUBY_RELEASE_YEAR 2013
 #define RUBY_RELEASE_MONTH 10
Index: ruby_2_0_0/test/ruby/test_io.rb
===================================================================
--- ruby_2_0_0/test/ruby/test_io.rb	(revision 43143)
+++ ruby_2_0_0/test/ruby/test_io.rb	(revision 43144)
@@ -1218,6 +1218,19 @@ class TestIO < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/test/ruby/test_io.rb#L1218
     end
   end
 
+  def test_close_read_write_separately
+    bug = '[ruby-list:49598]'
+    (1..10).each do |i|
+      assert_nothing_raised(IOError, "#{bug} trying ##{i}") do
+        IO.popen(EnvUtil.rubybin, "r+") {|f|
+          th = Thread.new {f.close_write}
+          f.close_read
+          th.join
+        }
+      end
+    end
+  end
+
   def test_pid
     r, w = IO.pipe
     assert_equal(nil, r.pid)
@@ -1234,6 +1247,17 @@ class TestIO < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/test/ruby/test_io.rb#L1247
     assert_raise(IOError) { pipe.pid }
   end
 
+  def tesst_pid_after_close_read
+    pid1 = pid2 = nil
+    IO.popen(["echo", ""], "r+") do |io|
+      pid1 = io.pid
+      io.close_read
+      pid2 = io.pid
+    end
+    assert_not_nil(pid1)
+    assert_equal(pid1, pid2)
+  end
+
   def make_tempfile
     t = Tempfile.new("test_io")
     t.binmode

Property changes on: ruby_2_0_0
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /trunk:r43112,43114,43117-43118


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

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