From 915ae780c37478fea358d6c77513a728e86a10f2 Mon Sep 17 00:00:00 2001 From: nobu Date: Wed, 6 Oct 2010 02:52:26 +0000 Subject: [PATCH] * io.c (fptr_finalize): write_mutex might have been destroyed already in finalization phase, as the order of finalizers is not guaranteed. rb_mutex_t should be used in place of Mutex object in the future. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@29415 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 7 +++++++ io.c | 12 +++++++++--- test/ruby/test_io.rb | 29 +++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5f719aaae7..b9207b80fa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Wed Oct 6 11:52:12 2010 Nobuyoshi Nakada + + * io.c (fptr_finalize): write_mutex might have been destroyed + already in finalization phase, as the order of finalizers is not + guaranteed. rb_mutex_t should be used in place of Mutex object + in the future. + Tue Oct 5 22:17:02 2010 wanabe * win32/mkexports.rb: revert r29320 and r29402. diff --git a/io.c b/io.c index 2a5a6452f7..c368ecb842 100644 --- a/io.c +++ b/io.c @@ -3459,7 +3459,7 @@ fptr_finalize(rb_io_t *fptr, int noraise) { VALUE err = Qnil; if (fptr->writeconv) { - if (fptr->write_lock) { + if (fptr->write_lock && !noraise) { struct finish_writeconv_arg arg; arg.fptr = fptr; arg.noalloc = noraise; @@ -3470,8 +3470,14 @@ fptr_finalize(rb_io_t *fptr, int noraise) } } if (fptr->wbuf_len) { - if (io_fflush(fptr) < 0 && NIL_P(err)) - err = noraise ? Qtrue : INT2NUM(errno); + if (noraise) { + if ((int)io_flush_buffer_sync(fptr) < 0 && NIL_P(err)) + err = Qtrue; + } + else { + if (io_fflush(fptr) < 0 && NIL_P(err)) + err = INT2NUM(errno); + } } if (IS_PREP_STDIO(fptr) || fptr->fd <= 2) { goto skip_fd_close; diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb index 1cfcba181a..0d89b58b59 100644 --- a/test/ruby/test_io.rb +++ b/test/ruby/test_io.rb @@ -1625,4 +1625,33 @@ End end end.each {|th| th.join} end + + def test_flush_in_finalizer1 + require 'tempfile' + bug3910 = '[ruby-dev:42341]' + path = Tempfile.new("bug3910").path + fds = [] + assert_nothing_raised(TypeError, bug3910) do + 500.times { + f = File.open(path, "w") + fds << f.fileno + f.print "hoge" + } + end + ensure + fds.each {|fd| IO.for_fd(fd).close rescue next} + end + + def test_flush_in_finalizer2 + require 'tempfile' + bug3910 = '[ruby-dev:42341]' + path = Tempfile.new("bug3910").path + 1.times do + io = open(path,"w") + io.print "hoge" + end + assert_nothing_raised(TypeError, bug3910) do + GC.start + end + end end