summaryrefslogtreecommitdiff
path: root/test/socket
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-06-15 19:38:49 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-06-15 19:38:49 +0000
commitb9a91334c50e5a0b8ea0a4b571cd3011228cba6c (patch)
tree2c2943128de42db8c8eba898a1c402c7d8bf8ca1 /test/socket
parent91af3e00d1bdf7aab0d8f413ebbc5494d017f08c (diff)
socket: allow exception-free nonblocking sendmsg/recvmsg
As documented before, exceptions are expensive and IO::Wait*able are too common in socket applications to be the exceptional case. Datagram sockets deserve the same API which stream sockets are allowed with read_nonblock and write_nonblock. Note: this does not offer a performance advantage under optimal conditions when both ends are equally matched in speed, but it it does make debug output cleaner by avoiding exceptions whenever the receiver slows down. * ext/socket/ancdata.c (bsock_sendmsg_internal, bsock_recvmsg_internal): support "exception: false" kwarg * ext/socket/init.c (rsock_s_recvfrom_nonblock): ditto * ext/socket/init.c (rsock_s_recvfrom_nonblock): use rsock_opt_false_p * ext/socket/socket.c (sock_connect_nonblock): ditto * ext/socket/rubysocket.h (rsock_opt_false_p): new function * ext/socket/basicsocket.c (bsock_recv_nonblock): update rdoc * ext/socket/udpsocket.c (udp_recvfrom_nonblock): ditto * test/socket/test_nonblock.rb: new tests [ruby-core:69542] [Feature #11229] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50910 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'test/socket')
-rw-r--r--test/socket/test_nonblock.rb44
1 files changed, 44 insertions, 0 deletions
diff --git a/test/socket/test_nonblock.rb b/test/socket/test_nonblock.rb
index f0fba3af74..4e14c9355a 100644
--- a/test/socket/test_nonblock.rb
+++ b/test/socket/test_nonblock.rb
@@ -1,6 +1,7 @@
begin
require "socket"
require "io/nonblock"
+ require "io/wait"
rescue LoadError
end
@@ -275,6 +276,17 @@ class TestSocketNonblock < Test::Unit::TestCase
}
end
+ def test_recvfrom_nonblock_no_exception
+ udp_pair do |s1, s2|
+ assert_equal :wait_readable, s1.recvfrom_nonblock(100, exception: false)
+ s2.send("aaa", 0, s1.getsockname)
+ assert s1.wait_readable
+ mesg, inet_addr = s1.recvfrom_nonblock(100, exception: false)
+ assert_equal(4, inet_addr.length)
+ assert_equal("aaa", mesg)
+ end
+ end
+
if defined?(UNIXSocket) && defined?(Socket::SOCK_SEQPACKET)
def test_sendmsg_nonblock_seqpacket
buf = '*' * 8192
@@ -286,6 +298,27 @@ class TestSocketNonblock < Test::Unit::TestCase
rescue NotImplementedError, Errno::ENOSYS, Errno::EPROTONOSUPPORT
skip "UNIXSocket.pair(:SEQPACKET) not implemented on this platform: #{$!}"
end
+
+ def test_sendmsg_nonblock_no_exception
+ buf = '*' * 128
+ UNIXSocket.pair(:SEQPACKET) do |s1, s2|
+ n = 0
+ Timeout.timeout(60) do
+ case rv = s1.sendmsg_nonblock(buf, exception: false)
+ when Integer
+ n += rv
+ when :wait_writable
+ break
+ else
+ flunk "unexpected return value: #{rv.inspect}"
+ end while true
+ assert_equal :wait_writable, rv
+ assert_operator n, :>, 0
+ end
+ end
+ rescue NotImplementedError, Errno::ENOSYS, Errno::EPROTONOSUPPORT
+ skip "UNIXSocket.pair(:SEQPACKET) not implemented on this platform: #{$!}"
+ end
end
def test_recvmsg_nonblock_error
@@ -297,6 +330,7 @@ class TestSocketNonblock < Test::Unit::TestCase
rescue Errno::EWOULDBLOCK
assert_kind_of(IO::WaitReadable, $!)
end
+ assert_equal :wait_readable, s1.recvmsg_nonblock(11, exception: false)
}
end
@@ -310,6 +344,16 @@ class TestSocketNonblock < Test::Unit::TestCase
}
end
+ def test_recv_nonblock_no_exception
+ tcp_pair {|c, s|
+ assert_equal :wait_readable, c.recv_nonblock(11, exception: false)
+ s.write('HI')
+ assert c.wait_readable
+ assert_equal 'HI', c.recv_nonblock(11, exception: false)
+ assert_equal :wait_readable, c.recv_nonblock(11, exception: false)
+ }
+ end
+
def test_connect_nonblock_error
serv = TCPServer.new("127.0.0.1", 0)
_, port, _, _ = serv.addr