summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--io.c29
-rw-r--r--test/ruby/test_io.rb101
-rw-r--r--test/ruby/test_io_m17n.rb46
4 files changed, 116 insertions, 66 deletions
diff --git a/ChangeLog b/ChangeLog
index b9fe0c4f57..1f8ba74732 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/io.c b/io.c
index 9752021119..20c093aa43 100644
--- a/io.c
+++ b/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);
diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb
index 9d2ecef725..dca78603c7 100644
--- a/test/ruby/test_io.rb
+++ b/test/ruby/test_io.rb
@@ -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)
-
- 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
+ IO.pipe {|r, w|
+ assert_equal(nil, r.pid)
+ assert_equal(nil, w.pid)
+ }
+
+ 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
diff --git a/test/ruby/test_io_m17n.rb b/test/ruby/test_io_m17n.rb
index 0b435dd8c1..e9e6a1cf83 100644
--- a/test/ruby/test_io_m17n.rb
+++ b/test/ruby/test_io_m17n.rb
@@ -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