Age | Commit message (Collapse) | Author |
|
|
|
|
|
* Introduction of Happy Eyeballs Version 2 (RFC8305) in Socket.tcp
This is an implementation of Happy Eyeballs version 2 (RFC 8305) in Socket.tcp.
[Background]
Currently, `Socket.tcp` synchronously resolves names and makes connection attempts with `Addrinfo::foreach.`
This implementation has the following two problems.
1. In name resolution, the program stops until the DNS server responds to all DNS queries.
2. In a connection attempt, while an IP address is trying to connect to the destination host and is taking time, the program stops, and other resolved IP addresses cannot try to connect.
[Proposal]
"Happy Eyeballs" ([RFC 8305](https://datatracker.ietf.org/doc/html/rfc8305)) is an algorithm to solve this kind of problem. It avoids delays to the user whenever possible and also uses IPv6 preferentially.
I implemented it into `Socket.tcp` by using `Addrinfo.getaddrinfo` in each thread spawned per address family to resolve the hostname asynchronously, and using `Socket::connect_nonblock` to try to connect with multiple addrinfo in parallel.
[Outcome]
This change eliminates a fatal defect in the following cases.
Case 1. One of the A or AAAA DNS queries does not return
---
require 'socket'
class Addrinfo
class << self
# Current Socket.tcp depends on foreach
def foreach(nodename, service, family=nil, socktype=nil, protocol=nil, flags=nil, timeout: nil, &block)
getaddrinfo(nodename, service, Socket::AF_INET6, socktype, protocol, flags, timeout: timeout)
.concat(getaddrinfo(nodename, service, Socket::AF_INET, socktype, protocol, flags, timeout: timeout))
.each(&block)
end
def getaddrinfo(_, _, family, *_)
case family
when Socket::AF_INET6 then sleep
when Socket::AF_INET then [Addrinfo.tcp("127.0.0.1", 4567)]
end
end
end
end
Socket.tcp("localhost", 4567)
---
Because the current `Socket.tcp` cannot resolve IPv6 names, the program stops in this case. It cannot start to connect with IPv4 address.
Though `Socket.tcp` with HEv2 can promptly start a connection attempt with IPv4 address in this case.
Case 2. Server does not promptly return ack for syn of either IPv4 / IPv6 address family
---
require 'socket'
fork do
socket = Socket.new(Socket::AF_INET6, :STREAM)
socket.setsockopt(:SOCKET, :REUSEADDR, true)
socket.bind(Socket.pack_sockaddr_in(4567, '::1'))
sleep
socket.listen(1)
connection, _ = socket.accept
connection.close
socket.close
end
fork do
socket = Socket.new(Socket::AF_INET, :STREAM)
socket.setsockopt(:SOCKET, :REUSEADDR, true)
socket.bind(Socket.pack_sockaddr_in(4567, '127.0.0.1'))
socket.listen(1)
connection, _ = socket.accept
connection.close
socket.close
end
Socket.tcp("localhost", 4567)
---
The current `Socket.tcp` tries to connect serially, so when its first name resolves an IPv6 address and initiates a connection to an IPv6 server, this server does not return an ACK, and the program stops.
Though `Socket.tcp` with HEv2 starts to connect sequentially and in parallel so a connection can be established promptly at the socket that attempted to connect to the IPv4 server.
In exchange, the performance of `Socket.tcp` with HEv2 will be degraded.
---
100.times { Socket.tcp("www.ruby-lang.org", 80) }
---
This is due to the addition of the creation of IO objects, Thread objects, etc., and calls to `IO::select` in the implementation.
* Avoid NameError of Socket::EAI_ADDRFAMILY in MinGW
* Support Windows with SO_CONNECT_TIME
* Improve performance
I have additionally implemented the following patterns:
- If the host is single-stack, name resolution is performed in the main thread. This reduces the cost of creating threads.
- If an IP address is specified, name resolution is performed in the main thread. This also reduces the cost of creating threads.
- If only one IP address is resolved, connect is executed in blocking mode. This reduces the cost of calling IO::select.
Also, I have added a fast_fallback option for users who wish not to use HE.
Here are the results of each performance test.
```ruby
require 'socket'
require 'benchmark'
HOSTNAME = "www.ruby-lang.org"
PORT = 80
ai = Addrinfo.tcp(HOSTNAME, PORT)
Benchmark.bmbm do |x|
x.report("Domain name") do
30.times { Socket.tcp(HOSTNAME, PORT).close }
end
x.report("IP Address") do
30.times { Socket.tcp(ai.ip_address, PORT).close }
end
x.report("fast_fallback: false") do
30.times { Socket.tcp(HOSTNAME, PORT, fast_fallback: false).close }
end
end
```
```
user system total real
Domain name 0.015567 0.032511 0.048078 ( 0.325284)
IP Address 0.004458 0.014219 0.018677 ( 0.284361)
fast_fallback: false 0.005869 0.021511 0.027380 ( 0.321891)
````
And this is the measurement result when executed in a single stack environment.
```
user system total real
Domain name 0.007062 0.019276 0.026338 ( 1.905775)
IP Address 0.004527 0.012176 0.016703 ( 3.051192)
fast_fallback: false 0.005546 0.019426 0.024972 ( 1.775798)
```
The following is the result of the run on Ruby 3.3.0.
(on Dual stack environment)
```
user system total real
Ruby 3.3.0 0.007271 0.027410 0.034681 ( 0.472510)
```
(on Single stack environment)
```
user system total real
Ruby 3.3.0 0.005353 0.018898 0.024251 ( 1.774535)
```
* Do not cache `Socket.ip_address_list`
As mentioned in the comment at https://github.com/ruby/ruby/pull/9374#discussion_r1482269186, caching Socket.ip_address_list does not follow changes in network configuration.
But if we stop caching, it becomes necessary to check every time `Socket.tcp` is called whether it's a single stack or not, which could further degrade performance in the case of a dual stack.
From this, I've changed the approach so that when a domain name is passed, it doesn't check whether it's a single stack or not and resolves names in parallel each time.
The performance measurement results are as follows.
require 'socket'
require 'benchmark'
HOSTNAME = "www.ruby-lang.org"
PORT = 80
ai = Addrinfo.tcp(HOSTNAME, PORT)
Benchmark.bmbm do |x|
x.report("Domain name") do
30.times { Socket.tcp(HOSTNAME, PORT).close }
end
x.report("IP Address") do
30.times { Socket.tcp(ai.ip_address, PORT).close }
end
x.report("fast_fallback: false") do
30.times { Socket.tcp(HOSTNAME, PORT, fast_fallback: false).close }
end
end
user system total real
Domain name 0.004085 0.011873 0.015958 ( 0.330097)
IP Address 0.000993 0.004400 0.005393 ( 0.257286)
fast_fallback: false 0.001348 0.008266 0.009614 ( 0.298626)
* Wait forever if fallback addresses are unresolved, unless resolv_timeout
Changed from waiting only 3 seconds for name resolution when there is no fallback address available, to waiting as long as there is no resolv_timeout.
This is in accordance with the current `Socket.tcp` specification.
* Use exact pattern to match IPv6 address format for specify address family
|
|
* Documentation consistency.
* Improve consistency of `pread`/`pwrite` implementation when given length.
* Remove HAVE_PREAD / HAVE_PWRITE - it is no longer optional.
Notes:
Merged-By: ioquatix <samuel@codeotaku.com>
|
|
generic RUBY_UBF_IO" on Windows. (#7848)
* Enable borked spec.
* Ensure win32 wrappers are visible and used.
* Reorganise `read`/`write`/`pipe` in `thread_spec.c`.
Notes:
Merged-By: ioquatix <samuel@codeotaku.com>
|
|
Notes:
Merged-By: ioquatix <samuel@codeotaku.com>
|
|
* Windows: Fix warning about undefined if_indextoname()
* Windows: Fix UNIXSocket on MINGW and make .pair more reliable
* Windows: Use nonblock=true for read tests with scheduler
* Windows: Move socket detection from File.socket? to File.stat
Add S_IFSOCK to Windows and interpret reparse points accordingly.
Enable tests that work now.
* Windows: Use wide-char functions to UNIXSocket
This fixes behaviour with non-ASCII characters.
It also fixes deletion of temporary UNIXSocket.pair files.
* Windows: Add UNIXSocket tests for specifics of Windows impl.
* Windows: fix VC build due to missing _snwprintf
Avoid usage of _snwprintf, since it fails linking ruby.dll like so:
linking shared-library x64-vcruntime140-ruby320.dll
x64-vcruntime140-ruby320.def : error LNK2001: unresolved external symbol snwprintf
x64-vcruntime140-ruby320.def : error LNK2001: unresolved external symbol vsnwprintf_l
whereas linking miniruby.exe succeeds.
This patch uses snprintf on the UTF-8 string instead.
Also remove branch GetWindowsDirectoryW, since it doesn't work.
* Windows: Fix dangling symlink test failures
Co-authored-by: Lars Kanis <kanis@comcard.de>
Notes:
Merged-By: ioquatix <samuel@codeotaku.com>
|
|
* Windows: Use readlink emulation for File.readlink
This fixes readlink emulation for the ERROR_MORE_DATA case and general error reporting.
It now releases GVL while readlink IO operation.
The dedicated rb_readlink was introduced in commit 2ffb87995a33cdc7ba609a4b867f03f18da0c3b3
in order to improve encoding and buffer allocation.
However the encoding issues are solved since ruby-3.0 switched to UTF-8
and the buffer allocation will be improved in a later commit.
* Windows: Increase the default buffer size for reparse point info
So far nearly all queries of reparse points needed two attempts to get enough buffer.
* Windows: Remove declaration of rb_w32_wreadlink
It was removed in commit 2f6fdd3aebdee2ce04d003b206f6da78120e8235
Notes:
Merged-By: ioquatix <samuel@codeotaku.com>
|
|
Get rid of the conflict with system-provided small `off_t`.
Notes:
Merged: https://github.com/ruby/ruby/pull/6329
|
|
[Misc #18891]
Notes:
Merged: https://github.com/ruby/ruby/pull/6094
|
|
Configuration for mingw32 can't detect 'shutdown' due to wrong -l
option even though it's available (this has been going on for a while,
and it needs to be fixed).
In this situation, include/ruby/missing.h declares a stub shutdown
function since 7ee786388a, and another shutdown decl is came from
system header. They are incompatible at stdcall attribute, so it
causes compilation failure.
This change defines a HAVE_SHUTDOWN to guard a newly introduced stub
decl in include/ruby/missing.h
Notes:
Merged: https://github.com/ruby/ruby/pull/5465
|
|
Notes:
Merged-By: kateinoigakukun
|
|
|
|
|
|
- prerequisite of supporting YJIT with VC++.
- note that now can specfily `--yjit` on mswin64, but not enabled
YJIT'ed code because of YJIT requires `OPT_DIRECT_THREADED_CODE`
or `OPT_CALL_THREADED_CODE` in `rb_yjit_compile_iseq`.
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/4783
|
|
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/3948
|
|
Co-Authored-By: Dāvis Mosāns <davispuh@gmail.com>
Notes:
Merged: https://github.com/ruby/ruby/pull/3948
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/3914
|
|
rb_w32_pipe_exec was removed in 1.9.3, at
commit:7ac32d7a16734ea66de15319bcff2fd429abae7f.
Notes:
Merged: https://github.com/ruby/ruby/pull/3914
|
|
* Windows: Read ENV names and values as UTF-8 encoded Strings
Implements issue #12650: fix https://bugs.ruby-lang.org/issues/12650
This also removes the special encoding for ENV['PATH'] and some
complexity in the code that is unnecessary now.
* Windows: Improve readablity of getenv() encoding
getenv() did use the expected codepage as an implicit parameter of the macro.
This is mis-leading since include/ruby/win32.h has a different definition.
Using the "cp" variable explicit (like the other function calls) makes it
more readable and consistent.
* Windows: Change external C-API macros getenv() and execv() to use UTF-8
They used to process and return strings with locale encoding,
but since all ruby-internal spawn and environment functions use UTF-8,
it makes sense to change the C-API equally.
Notes:
Merged-By: nurse <naruse@airemix.jp>
|
|
[Bug #12230]
|
|
trying to solve build problem of MinGW. see [Bug #14165]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61119 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
* win32/win32.c, include/ruby/win32.h (stati128, rb_{,u,l,ul}stati128): rename
from stati64ns, change the type of st_ino to 64bit and added st_inohigh.
* dir.c, file.c (stat, lstat): follow above changes.
* file.c (rb_stat_ino): support 128bit ino.
* win32/win32.c (rb_{,u,l,ul}stati128): ditto.
[Feature #13731]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61096 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
Support nanosec file timestamp on Windows 8 or later.
Original patches are written by kubo (Kubo Takehiro).
Windows 7 and earlier also supports nanosec file timestamp, but it's too
accurate than system time. so, this feature is disabled on such versions.
[Feature #13726]
this change also includes [Misc #13702]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61013 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
Fix a warning in ruby/win32.h which can cause failures with mkmf
The return value is implicit type casted from 'long double' to 'double', currently.
This causes a gcc warning like this:
```
In file included from C:\Ruby24-x64\include\ruby-2.4.0/ruby/defines.h:243:0,
from C:\Ruby24-x64\include\ruby-2.4.0/ruby/ruby.h:36,
from C:\Ruby24-x64\include\ruby-2.4.0/ruby.h:33,
from conftest.c:1:
C:\Ruby24-x64\include\ruby-2.4.0/ruby/win32.h: In function 'rb_w32_pow':
C:\Ruby24-x64\include\ruby-2.4.0/ruby/win32.h:786:12: warning: conversion to 'double' from 'long double' may alter its value [-Wfloat-conversion]
return powl(x, y);
^~~~~~~~~~
```
This is fixed by the attached explicit type cast.
Moreover when CFLAGS is set to '-Wconversion', it prevents the compiler from
building. This is the case at the nokogiri gem.
The original issue arose at RubyInstaller2: https://github.com/oneclick/rubyinstaller2/commit/576a0eb70aa9348b366c3ecfe83c67811b7bcb9b
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58423 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
* configure.in: check whether frexp and modf are broken.
* include/ruby/win32.h (frexp, modf): ignore bad declarations when
compiling as C++. [ruby-core:79859] [Bug #13267]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57762 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
* include/ruby/win32.h (rb_w32_sysinit): declare.
[ruby-core:78444] [Bug #12994]
* ruby.c (ruby_sysinit): follow above change.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57072 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
truncate alternative which accepts UTF-8 path.
* file.c (truncate): use above function.
[Bug #12340]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54889 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
* include/ruby/win32.h (O_SHARE_DELETE): change to fit Fixnum
limit. [ruby-core:74285] [Bug #12171]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54094 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
* win32/win32.c (fcntl): implement F_GETFD, F_SETFD, and
F_DUPFD_CLOEXEC.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51831 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
* include/ruby/win32.h: fix macro name for VC runtime version,
RT_VER is only in Makefile.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51760 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
* win32/win32.c (w32_symlink): implement symlink().
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51674 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
* include/ruby/win32.h: include windows.h before winsock2.h,
because mswsock.h included by the former uses SOCKET defined
after it in the latter. fix a build failure with VC6.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51312 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
on Windows.
* include/win32/win32.c (O_SHARE_DELETE): new pseudo file mode flag.
* win32/win32.c (rb_w32_{w,}open): support above flag. [EXPERIMENTAL]
* NEWS: mention about this feature.
[Feature #11218] [ruby-dev:49022]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50848 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
ruby (before 1.8), but not now.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50381 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
* include/ruby/win32.h: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50380 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
* win32/win32.c (wreadlink, rb_w32_ureadlink): implement readlink().
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50062 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
* win32/win32.c (winnt_stat): stat with following symbolic links.
* win32/win32.c (winnt_lstat): rename old winnt_stat, which does
not follow symbolic links.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50060 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
* win32/win32.c (fileattr_to_unixmode): set symlink for reparse
points.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50022 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
function to support nonblock-mode of pipes.
* win32/win32.c (rb_w32_read): nonblock-mode pipe returns ERROR_NO_DATA
if there is no data, but also returns it if remote-end is closed.
* win32/win32.c (rb_w32_write): if cannot to write any data, it may be
blocking.
* io.c (rb_io_set_nonblock): use rb_w32_set_nonblock for Windows.
* ext/io/nonblock/nonblock.c (rb_io_nonblock_set): use ruby's API when
setting nonblock-mode.
* test/ruby/test_io.rb: test nonblock pipes on Windows.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@48361 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46042 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
statfs(2) clone. [EXPERIMENTAL]
* file.c (rb_io_statfs): use above function.
* configure.in, win32/Makefile.sub (struct statfs): available.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45672 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
* win32/win32.c (rb_w32_sysinit): use WCHAR version of GetCommandLine()
internally.
* win32/win32.c (w32_cmdvector): renamed from rb_w32_cmdvector. use
WCHAR* instead of char* internally.
these changes are expected to not changing the behavior yet.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45592 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
* win32/win32.c (rb_w32_wstr_to_mbstr, rb_w32_mbstr_to_wstr): make
WCHAR/mb conversion functions public.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45521 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
* include/ruby/win32.h, win32/win32.c (rb_w32_inet_pton): add a
wrapper function for inet_pton minimum supported client is
Vista, as well as inet_ntop.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45150 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
include/ruby/io.h,
include/ruby/ruby.h,
include/ruby/win32.h,
include/ruby/backward/rubysig.h,
bignum.c,
gc.c,
io.c,
process.c,
safe.c,
struct.c,
thread.c,
ext/socket/rubysocket.h,
ext/-test-/old_thread_select: Remove deprecated definitions
[ruby-core:60581] [Feature #9502]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44955 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
* include/ruby/win32.h (strtoll, strtoull): VC8 and later until
VC12 have LONG_LONG but it is _int64, and provide i64 version
functions only.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44875 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|
|
* win32/win32.c (rb_w32_dup2): extract from rb_cloexec_dup2() and
redirect_dup2().
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43890 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
|