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
* ext/socket/ancdata.c (bsock_sendmsg_internal,
bsock_recvmsg_internal):
avoid redundant fcntl on Linux
[ruby-core:69154] [Feature #11145]
* ext/socket/init.c (rsock_s_recvfrom_nonblock): ditto
* ext/socket/rubysocket.h (MSG_DONTWAIT_RELIABLE): new macro
MSG_DONTWAIT is enough to force non-blocking I/O under Linux,
so avoid changing the state of a socket. This will allow certain
threads to do a non-destructive non-blocking "peek" while others
block (without relying on an extra ppoll syscall).
We shall be conservative about enabling this feature since some
OSes may have incomplete support for MSG_DONTWAIT. I shall
defer to a FreeBSD expert to enable that for FreeBSD.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50666 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This is analogous to functionality found in IO#read_nonblock and
IO#wait_nonblock. Raising exceptions for common failures on
non-blocking servers is expensive and makes $DEBUG too noisy.
Benchmark results:
user system total real
default 2.790000 0.870000 3.660000 ( 3.671597)
exception: false 1.120000 0.800000 1.920000 ( 1.922032)
exception: false (cached arg) 0.820000 0.770000 1.590000 ( 1.589267)
--------------------- benchmark script ------------------------
require 'socket'
require 'benchmark'
require 'tmpdir'
nr = 1000000
Dir.mktmpdir('nb_bench') do |path|
sock_path = "#{path}/test.sock"
s = UNIXServer.new(sock_path)
Benchmark.bmbm do |x|
x.report("default") do
nr.times do
begin
s.accept_nonblock
rescue IO::WaitReadable
end
end
end
x.report("exception: false") do
nr.times do
begin
s.accept_nonblock(exception: false)
rescue IO::WaitReadable
abort "should not raise"
end
end
end
x.report("exception: false (cached arg)") do
arg = { exception: false }
nr.times do
begin
s.accept_nonblock(arg)
rescue IO::WaitReadable
abort "should not raise"
end
end
end
end
end
* ext/socket/init.c (rsock_s_accept_nonblock):
support exception: false
[ruby-core:66385] [Feature #10532]
* ext/socket/init.c (rsock_init_socket_init): define new symbols
* ext/socket/rubysocket.h: adjust prototype
* ext/socket/socket.c (sock_accept_nonblock): support exception: false
* ext/openssl/ossl_ssl.c (ossl_ssl_accept_nonblock): ditto
* ext/socket/socket.c (Init_socket): adjust accept_nonblock definition
* ext/openssl/ossl_ssl.c (Init_ossl_ssl): ditto
* ext/socket/tcpserver.c (rsock_init_tcpserver): ditto
* ext/socket/unixserver.c (rsock_init_unixserver): ditto
* ext/socket/tcpserver.c (tcp_accept_nonblock): adjust
rsock_s_accept_nonblock call
* ext/socket/unixserver.c (unix_accept_nonblock): ditto
* ext/openssl/ossl_ssl.c (ossl_start_ssl): support no_exception
* ext/openssl/ossl_ssl.c (ossl_ssl_connect): adjust ossl_start_ssl call
* ext/openssl/ossl_ssl.c (ossl_ssl_connect_nonblock): ditto
* ext/openssl/ossl_ssl.c (ossl_ssl_accept): ditto
* test/socket/test_nonblock.rb (test_accept_nonblock): test for
"exception :false"
* test/socket/test_tcp.rb (test_accept_nonblock): new test
* test/socket/test_unix.rb (test_accept_nonblock): ditto
* test/openssl/test_pair.rb (test_accept_nonblock_no_exception): ditto
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49948 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
(sockopt_inspect): Use inspect_tcp_info.
* ext/socket/extconf.rb: Check tcp_info related things.
* ext/socket/rubysocket.h: Include netinet/tcp_fsm.h if available.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46017 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* ext/socket/extconf.rb: check for if_nametoindex() for
i686-w64-mingw32, and check for declarations of if_indextoname() and
if_nametoindex().
* ext/socket/ifaddr.c (ifaddr_ifindex): not-implement unless
if_nametoindex() is available.
* ext/socket/rubysocket.h: declare if_indextoname() and
if_nametoindex() if available but not declared.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40738 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
ext/socket/ancdata.c: Use HAVE_STRUCT_MSGHDR_MSG_CONTROL instead
of HAVE_ST_MSG_CONTROL.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40623 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* ext/socket/raddrinfo.c (ext/socket/raddrinfo.c): Reject too long
Linux abstract socket name.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40335 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
(rsock_sockaddr_string_value_with_addrinfo): New declaration.
(rsock_addrinfo_inspect_sockaddr): Ditto.
(rsock_sys_fail_addrinfo): Ditto.
(rsock_sys_fail_sockaddr_or_addrinfo): Ditto.
* ext/socket/raddrinfo.c (rsock_addrinfo_inspect_sockaddr): Renamed
from addrinfo_inspect_sockaddr and exported.
(rsock_sockaddr_string_value_with_addrinfo): New function to obtain
string and possibly addrinfo object.
* ext/socket/socket.c (rsock_sys_fail_sockaddr): Don't use
rsock_sys_fail_host_port which is IP dependent. Invoke
rsock_sys_fail_addrinfo.
(rsock_sys_fail_addrinfo): New function using
rsock_addrinfo_inspect_sockaddr.
(rsock_sys_fail_addrinfo_or_sockaddr): New function.
(sock_connect): Use SockAddrStringValueWithAddrinfo and
rsock_sys_fail_addrinfo_or_sockaddr.
(sock_connect_nonblock): Ditto.
(sock_bind): Ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40154 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* ext/socket/raddrinfo.c (rsock_make_hostent): ai_addrlen is not
size_t but socklen_t.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39251 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
socket address.
* ext/socket/rubysocket.h (rsock_make_ipaddr): add an argument for
socket address length.
(rsock_ipaddr): ditto.
* ext/socket/ipsocket.c (ip_addr): pass length to rsock_ipaddr.
(ip_peeraddr): ditto.
(ip_s_getaddress): pass length to rsock_make_ipaddr.
* ext/socket/socket.c (make_addrinfo): pass length to rsock_ipaddr.
(sock_s_getnameinfo): pass actual address length to rb_getnameinfo.
(sock_s_unpack_sockaddr_in): pass length to rsock_make_ipaddr.
* ext/socket/init.c (rsock_s_recvfrom): pass length to rsock_ipaddr.
(rsock_s_recvfrom_nonblock): ditto.
* ext/socket/tcpsocket.c (tcp_sockaddr): pass length to
rsock_make_ipaddr.
* ext/socket/raddrinfo.c (make_ipaddr0): add an argument for socket
address length. pass the length to rb_getnameinfo.
(rsock_ipaddr): ditto.
(rsock_make_ipaddr): add an argument for socket address length.
pass the length to make_ipaddr0.
(make_inetaddr): pass length to make_ipaddr0.
a local variable renamed.
(host_str): a local variable renamed.
(port_str): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39239 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
use HAVE_STRUCT_SOCKADDR_SA_LEN and HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
instead.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39230 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* ext/socket/rubysocket.h: define socklen_t if not available.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39225 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
rsock_unixpath_len, because it returns not the length of the path,
but the length of a socket address for the path.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38943 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
ext/socket/unixsocket.c (unixsock_connect_internal,
rsock_init_unixsock): calculate the correct address length of
an abstract socket. Without this fix, sizeof(struct sockaddr_un)
is specified as the length of an abstract socket for bind(2) or
connect(2), so the address of the socket is filled with extra NUL
characters. See unix(7) for details.
* ext/socket/lib/socket.rb (unix_server_socket): don't access the
file system if the platform is Linux and path starts with NUL,
which means that the socket is an abstract socket.
* test/socket/test_unix.rb: related test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38939 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Addrinfo#ipv6_unique_local? to detect RFC 4193 unique local
addresses. Part of #6692
* ext/socket/rubysocket.h: Add IN6_IS_ADDR_UNIQUE_LOCAL macro if
missing.
* test/socket/test_addrinfo.rb: Test for ipv6_unqiue_local?
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36474 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
r33876. [ruby-core:41475] [Bug #5706]
* ext/socket/extconf.rb: the alternative hack for [Bug #5675].
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33947 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
from intern.h to internal.h. It's still experimental API and
need more discussion. [ruby-dev:43698]
* include/ruby/intern.h: ditto.
* ext/socket/rubysocket.h: include internal.h.
* ext/socket/depend: add internal.h dependency.
* ext/socket/extconf.rb: add $INCFLAGS to topdir.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32187 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
blocking region with GIL released, for fd.
* thread.c (rb_thread_fd_close): implement. [ruby-core:35203]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@30852 b2dd03c8-39d4-4d8f-98ff-823fe69b080e