Bug #10153
closedFile.open block does not throw "No space left on device (Errno::ENOSPC)" if the data fits the buffer of IO.write
Description
When writing to file in disk using File.open with a block as an argument, if the diskspace is full and IO.write does not flush right away, the block just exits successfully instead of throwing Errno:ENOSPC.
Setup: Drive partition needs to be full
Eg. of a write that will succeed normally with no exception given that the drive is full (this means that the expected failure is being swallowed)
File.open('/full_drive/test.txt','wb') do |file|
file.write("test")
end
#This will complete normally because the "test" data does not get flushed
#This will leave a 0kb file on the disk
Eg. force a flush to see the error
File.open('/full_drive/test.txt','wb') do |file|
file.write("test")
file.flush
end
#This will throw Errno::ENOSPC
#This will leave a 0kb file on the disk
Eg. write a large enough data that file.write will flush by itself (most likely it hits the buffer cap)
fills = '1'*1048576
File.open('/full_drive/test.txt','wb') do |file|
file.write(fills)
end
#This will throw Errno::ENOSPC
#This will leave a 0kb file on the disk
Eg. When not using File.open block argument and closing the IO with an ensure block
begin
io = File.open('/full_drive/test.txt', 'wb')
io.write("test")
ensure
io.close
end
#This will throw Errno::ENOSPC
#This will leave a 0kb file on the disk
Currently tested in RHEL5.
Notes:
- I've encountered this in ruby-1.9.2
- I've tested this with ruby-2.1.2
- I'm not sure if the issue is because of File.open usage of c-extension rb_ensure or io_close. reference: (http://ruby-doc.org/core-1.9.3/File.html#method-c-open)
Updated by znz (Kazuhiro NISHIYAMA) about 10 years ago
- Priority changed from 5 to Normal
- Target version changed from 2.6 to 2.2.0
I can reproduce 2.2.0dev with /dev/full
.
% ruby -ve 'File.open("/dev/full", "w"){|f|f.puts "test"}'
ruby 2.2.0dev (2014-06-28 trunk 46598) [x86_64-linux]
% ruby -ve 'File.open("/dev/full", "w"){|f|f.puts "test"; f.flush}'
ruby 2.2.0dev (2014-06-28 trunk 46598) [x86_64-linux]
-e:1:in `flush': No space left on device (Errno::ENOSPC)
from -e:1:in `block in <main>'
from -e:1:in `open'
from -e:1:in `<main>'
%
Updated by nobu (Nobuyoshi Nakada) about 10 years ago
- Status changed from Open to Assigned
- Assignee set to matz (Yukihiro Matsumoto)
This behavior was introduced at r10623 by matz, but the commit log is only:
* io.c (io_close): always calls "close" method of the receiver.
[ruby-core:6911] [ruby-core:8112]
Updated by nobu (Nobuyoshi Nakada) about 10 years ago
- Status changed from Assigned to Closed
- % Done changed from 0 to 100
Applied in changeset r47288.
io.c: do not swallow exceptions at end of block
- io.c (io_close): ignore only "closed stream" IOError and
NoMethodError, do not swallow other exceptions at the end of
block. [ruby-core:64463] [Bug #10153]
Updated by nobu (Nobuyoshi Nakada) about 10 years ago
Seems intended to ignore IOError
and NoMethodError
.
Updated by nagachika (Tomoyuki Chikanaga) about 10 years ago
- Backport changed from 2.0.0: UNKNOWN, 2.1: UNKNOWN to 2.0.0: REQUIRED, 2.1: REQUIRED
Updated by butching314 (Marvin Reyes) about 10 years ago
What is the conclusion for this post?
Updated by nagachika (Tomoyuki Chikanaga) about 10 years ago
- Backport changed from 2.0.0: REQUIRED, 2.1: REQUIRED to 2.0.0: REQUIRED, 2.1: DONE
Backported into ruby_2_1
branch at r47486.
Updated by usa (Usaku NAKAMURA) about 10 years ago
- Backport changed from 2.0.0: REQUIRED, 2.1: DONE to 2.0.0: DONE, 2.1: DONE
backported into ruby_2_0_0
at r47503.
Updated by shyouhei (Shyouhei Urabe) over 7 years ago
- Related to Bug #13405: IO#close raises "stream closed" added