From: Mauricio Fernandez Date: 2005-12-16T10:45:35+09:00 Subject: [PATCH] Re: IO.open not calling close in block form? On Fri, Dec 16, 2005 at 08:23:02AM +0900, Daniel Berger wrote: > What happened to the block form of IO.open after 1.8.2? It's supposed to > ensure 'close' is called, right? > > class Foo < IO > def close > STDOUT.puts "Hello" > super > end > end > > if $0 == __FILE__ > Foo.open(File.open("testio.txt","w+").fileno){ |fh| > fh.puts "hello" > } > end FWIW batsman@tux-chan:/tmp$ cat io1.rb File.open("testio.txt", "w") do |f| def f.close; $stdout.puts "CLOSE" end end batsman@tux-chan:/tmp$ ruby -v io1.rb ruby 1.8.3 (2005-09-24) [i686-linux] batsman@tux-chan:/tmp$ See [1]. What about this? --- ruby1.8.orig/io.c 2005-12-16 02:26:26.000000000 +0100 +++ ruby1.8/io.c 2005-12-16 02:32:09.000000000 +0100 @@ -2146,17 +2146,6 @@ return Qnil; } -static VALUE -io_close(io) - VALUE io; -{ - if (TYPE(io) == T_FILE) { - rb_io_close(io); - return Qnil; - } - return rb_funcall(io, rb_intern("close"), 0, 0); -} - /* * call-seq: * ios.closed? => true or false @@ -2186,6 +2175,16 @@ return (fptr->f || fptr->f2)?Qfalse:Qtrue; } +static VALUE +io_close(io) + VALUE io; +{ + if (!RTEST(rb_io_closed(io))) + return rb_funcall(io, rb_intern("close"), 0, 0); + + return Qnil; +} + /* * call-seq: * ios.close_read => nil $ ./ruby -ve 'open("/dev/null") {|f| def f.close; $stdout.puts "closed"; end; }' ruby 1.8.4 (2005-11-02) [i686-linux] closed $ ./ruby -ve 'open("/dev/null") {|f| f.close; raise ArgumentError }' ruby 1.8.4 (2005-11-02) [i686-linux] -e:1: ArgumentError (ArgumentError) from -e:1 $ ./ruby -ve 'open("/dev/null") {|f| def f.close; $stdout.puts "closed"; end; raise ArgumentError }' ruby 1.8.4 (2005-11-02) [i686-linux] closed -e:1: ArgumentError (ArgumentError) from -e:1 [1] Tue Sep 20 00:34:07 2005 Yukihiro Matsumoto * io.c (io_close): call rb_io_close() directly if io is a T_FILE object. [ruby-dev:27156] -- Mauricio Fernandez