* io.c (rb_io_s_pipe): Close pipes if io_encoding_set() raises an

exception.
  (io_encoding_set_v): New function.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46225 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
akr 2014-05-29 11:29:47 +00:00
Родитель 2ad2007307
Коммит be4d1fd953
4 изменённых файлов: 115 добавлений и 65 удалений

Просмотреть файл

@ -1,3 +1,9 @@
Thu May 29 19:47:08 2014 Tanaka Akira <akr@fsij.org>
* io.c (rb_io_s_pipe): Close pipes if io_encoding_set() raises an
exception.
(io_encoding_set_v): New function.
Thu May 29 19:42:49 2014 Tanaka Akira <akr@fsij.org>
* lib/csv.rb (CSV.open): Close the opened file when an exception

29
io.c
Просмотреть файл

@ -9384,6 +9384,21 @@ io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
}
struct io_encoding_set_args {
rb_io_t *fptr;
VALUE v1;
VALUE v2;
VALUE opt;
};
static VALUE
io_encoding_set_v(VALUE v)
{
struct io_encoding_set_args *arg = (struct io_encoding_set_args *)v;
io_encoding_set(arg->fptr, arg->v1, arg->v2, arg->opt);
return Qnil;
}
static VALUE
pipe_pair_close(VALUE rw)
{
@ -9458,6 +9473,7 @@ rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
VALUE r, w, args[3], v1, v2;
VALUE opt;
rb_io_t *fptr, *fptr2;
struct io_encoding_set_args ies_args;
int fmode = 0;
VALUE ret;
@ -9475,7 +9491,18 @@ rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
rb_jump_tag(state);
}
GetOpenFile(r, fptr);
io_encoding_set(fptr, v1, v2, opt);
ies_args.fptr = fptr;
ies_args.v1 = v1;
ies_args.v2 = v2;
ies_args.opt = opt;
rb_protect(io_encoding_set_v, (VALUE)&ies_args, &state);
if (state) {
close(pipes[1]);
io_close(r);
rb_jump_tag(state);
}
args[1] = INT2NUM(pipes[1]);
args[2] = INT2FIX(O_WRONLY);
w = rb_protect(io_new_instance, (VALUE)args, &state);

Просмотреть файл

@ -1087,13 +1087,17 @@ class TestIO < Test::Unit::TestCase
def test_dup
ruby do |f|
f2 = f.dup
f.puts "foo"
f2.puts "bar"
f.close_write
f2.close_write
assert_equal("foo\nbar\n", f.read)
assert_equal("", f2.read)
begin
f2 = f.dup
f.puts "foo"
f2.puts "bar"
f.close_write
f2.close_write
assert_equal("foo\nbar\n", f.read)
assert_equal("", f2.read)
ensure
f2.close
end
end
end
@ -1396,18 +1400,22 @@ class TestIO < Test::Unit::TestCase
end
def test_pid
r, w = IO.pipe
assert_equal(nil, r.pid)
assert_equal(nil, w.pid)
IO.pipe {|r, w|
assert_equal(nil, r.pid)
assert_equal(nil, w.pid)
}
pipe = IO.popen(EnvUtil.rubybin, "r+")
pid1 = pipe.pid
pipe.puts "p $$"
pipe.close_write
pid2 = pipe.read.chomp.to_i
assert_equal(pid2, pid1)
assert_equal(pid2, pipe.pid)
pipe.close
begin
pipe = IO.popen(EnvUtil.rubybin, "r+")
pid1 = pipe.pid
pipe.puts "p $$"
pipe.close_write
pid2 = pipe.read.chomp.to_i
assert_equal(pid2, pid1)
assert_equal(pid2, pipe.pid)
ensure
pipe.close
end
assert_raise(IOError) { pipe.pid }
end
@ -2382,6 +2390,7 @@ End
t.close
1.times do
io = open(path,"w")
io.instance_variable_set(:@test_flush_in_finalizer2, true)
io.print "hoge"
end
assert_nothing_raised(TypeError, bug3910) do
@ -2389,6 +2398,12 @@ End
end
t.close!
}
ensure
ObjectSpace.each_object(File) {|f|
if f.instance_variables.include?(:@test_flush_in_finalizer2)
f.close
end
}
end
def test_readlines_limit_0
@ -2999,41 +3014,41 @@ End
bug8669 = '[ruby-core:56121] [Bug #8669]'
str = ""
r, = IO.pipe
t = Thread.new { r.read(nil, str) }
sleep 0.1 until t.stop?
t.raise
sleep 0.1 while t.alive?
assert_nothing_raised(RuntimeError, bug8669) { str.clear }
ensure
t.kill
IO.pipe {|r,|
t = Thread.new { r.read(nil, str) }
sleep 0.1 until t.stop?
t.raise
sleep 0.1 while t.alive?
assert_nothing_raised(RuntimeError, bug8669) { str.clear }
assert_raise(RuntimeError) { t.join }
}
end
def test_readpartial_unlocktmp_ensure
bug8669 = '[ruby-core:56121] [Bug #8669]'
str = ""
r, = IO.pipe
t = Thread.new { r.readpartial(4096, str) }
sleep 0.1 until t.stop?
t.raise
sleep 0.1 while t.alive?
assert_nothing_raised(RuntimeError, bug8669) { str.clear }
ensure
t.kill
IO.pipe {|r, w|
t = Thread.new { r.readpartial(4096, str) }
sleep 0.1 until t.stop?
t.raise
sleep 0.1 while t.alive?
assert_nothing_raised(RuntimeError, bug8669) { str.clear }
assert_raise(RuntimeError) { t.join }
}
end
def test_sysread_unlocktmp_ensure
bug8669 = '[ruby-core:56121] [Bug #8669]'
str = ""
r, = IO.pipe
t = Thread.new { r.sysread(4096, str) }
sleep 0.1 until t.stop?
t.raise
sleep 0.1 while t.alive?
assert_nothing_raised(RuntimeError, bug8669) { str.clear }
ensure
t.kill
IO.pipe {|r, w|
t = Thread.new { r.sysread(4096, str) }
sleep 0.1 until t.stop?
t.raise
sleep 0.1 while t.alive?
assert_nothing_raised(RuntimeError, bug8669) { str.clear }
assert_raise(RuntimeError) { t.join }
}
end
end

Просмотреть файл

@ -2142,32 +2142,34 @@ EOT
def test_textmode_paragraph_nonasciicompat
bug3534 = ['[ruby-dev:41803]', '[Bug #3534]']
r, w = IO.pipe
[Encoding::UTF_32BE, Encoding::UTF_32LE,
Encoding::UTF_16BE, Encoding::UTF_16LE,
Encoding::UTF_8].each do |e|
r.set_encoding(Encoding::US_ASCII, e)
wthr = Thread.new{ w.print(bug3534[0], "\n\n\n\n", bug3534[1], "\n") }
assert_equal((bug3534[0]+"\n\n").encode(e), r.gets(""), bug3534[0])
assert_equal((bug3534[1]+"\n").encode(e), r.gets(), bug3534[1])
wthr.join
end
IO.pipe {|r, w|
[Encoding::UTF_32BE, Encoding::UTF_32LE,
Encoding::UTF_16BE, Encoding::UTF_16LE,
Encoding::UTF_8].each do |e|
r.set_encoding(Encoding::US_ASCII, e)
wthr = Thread.new{ w.print(bug3534[0], "\n\n\n\n", bug3534[1], "\n") }
assert_equal((bug3534[0]+"\n\n").encode(e), r.gets(""), bug3534[0])
assert_equal((bug3534[1]+"\n").encode(e), r.gets(), bug3534[1])
wthr.join
end
}
end
def test_binmode_paragraph_nonasciicompat
bug3534 = ['[ruby-dev:41803]', '[Bug #3534]']
r, w = IO.pipe
r.binmode
w.binmode
[Encoding::UTF_32BE, Encoding::UTF_32LE,
Encoding::UTF_16BE, Encoding::UTF_16LE,
Encoding::UTF_8].each do |e|
r.set_encoding(Encoding::US_ASCII, e)
wthr = Thread.new{ w.print(bug3534[0], "\n\n\n\n", bug3534[1], "\n") }
assert_equal((bug3534[0]+"\n\n").encode(e), r.gets(""), bug3534[0])
assert_equal((bug3534[1]+"\n").encode(e), r.gets(), bug3534[1])
wthr.join
end
IO.pipe {|r, w|
r.binmode
w.binmode
[Encoding::UTF_32BE, Encoding::UTF_32LE,
Encoding::UTF_16BE, Encoding::UTF_16LE,
Encoding::UTF_8].each do |e|
r.set_encoding(Encoding::US_ASCII, e)
wthr = Thread.new{ w.print(bug3534[0], "\n\n\n\n", bug3534[1], "\n") }
assert_equal((bug3534[0]+"\n\n").encode(e), r.gets(""), bug3534[0])
assert_equal((bug3534[1]+"\n").encode(e), r.gets(), bug3534[1])
wthr.join
end
}
end
def test_puts_widechar