mirror of
https://github.com/ruby/ruby.git
synced 2025-09-17 09:33:59 +02:00
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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_0_0@43144 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
3cfa0074d9
commit
514878d15c
4 changed files with 45 additions and 5 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
|||
Sat Oct 5 02:14:56 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* 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@ruby-lang.org>
|
||||
|
||||
* 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@ruby-lang.org>
|
||||
|
||||
* vm_method.c (rb_undef): raise a NameError if the original method
|
||||
|
|
13
io.c
13
io.c
|
@ -4369,11 +4369,16 @@ rb_io_close_read(VALUE io)
|
|||
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)
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1218,6 +1218,19 @@ class TestIO < Test::Unit::TestCase
|
|||
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
|
|||
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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue