1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/test/io/nonblock/test_flush.rb
normal 6a65f2b1e4 io + socket: make pipes and sockets nonblocking by default
All normal Ruby IO methods (IO#read, IO#gets, IO#write, ...) are
all capable of appearing to be "blocking" when presented with a
file description with the O_NONBLOCK flag set; so there is
little risk of incompatibility within Ruby-using programs.

The biggest compatibility risk is when spawning external
programs.  As a result, stdin, stdout, and stderr are now always
made blocking before exec-family calls.

This change will make an event-oriented MJIT usable if it is
waiting on pipes on POSIX_like platforms.

It is ALSO necessary to take advantage of (proposed lightweight
concurrency (aka "auto-Fiber") or any similar proposal for
network concurrency: https://bugs.ruby-lang.org/issues/13618

Named-pipe (FIFO) are NOT yet non-blocking by default since
they are rarely-used and may introduce compatibility problems
and extra syscall overhead for a common path.

Please revert this commit if there are problems and if I am afk
since I am afk a lot, lately.

[ruby-core:89950] [Bug #14968]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65922 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-11-22 08:46:51 +00:00

73 lines
1.6 KiB
Ruby

# frozen_string_literal: false
require 'test/unit'
require 'timeout'
begin
require 'io/nonblock'
rescue LoadError
end
class TestIONonblock < Test::Unit::TestCase
def test_flush
IO.pipe {|r, w|
return if flush_test(r, w)
}
require 'socket';
Socket.pair(:INET, :STREAM) {|s1, s2|
return if flush_test(s1, s2)
}
skip "nonblocking IO did not work"
end
def flush_test(r, w)
begin
w.nonblock = true
rescue Errno::EBADF
return false
end
w.sync = false
w << "b"
w.flush
w << "a" * 4096
result = ""
Timeout.timeout(10) {
t0 = Thread.new {
Thread.pass
w.close
}
t = Thread.new {
while (Thread.pass; s = r.read(4096))
result << s
end
}
begin
w.flush # assert_raise(IOError, "[ruby-dev:24985]") {w.flush}
rescue Errno::EBADF, IOError
# ignore [ruby-dev:35638]
end
assert_nothing_raised {t.join}
t0.join
}
assert_equal(4097, result.size)
true
end
def test_nonblock
IO.pipe {|r, w|
w.nonblock = false
assert_equal(false, w.nonblock?)
w.nonblock do
assert_equal(true, w.nonblock?)
w.nonblock(false) do
assert_equal(false, w.nonblock?)
w.nonblock(false) do
assert_equal(false, w.nonblock?)
end
assert_equal(false, w.nonblock?)
end
assert_equal(true, w.nonblock?)
end
assert_equal(false, w.nonblock?)
}
rescue NotImplementedError
end
end if IO.method_defined?(:nonblock)