Commit graph

102 commits

Author SHA1 Message Date
Misaki Shioi
ba490059b4
[Feature #21347] Add open_timeout as an overall timeout option for TCPSocket.new (#13909)
* [Feature #21347] Add `open_timeout` as an overall timeout option for `TCPSocket.new`

With this change, `TCPSocket.new` now accepts the `open_timeout` option.
This option raises an exception if the specified number of seconds has elapsed since the start of the method call,
even if the operation is still in the middle of name resolution or connection attempts.

The addition of this option follows the same intent as the previously merged change to `Socket.tcp`.
[Feature #21347](https://bugs.ruby-lang.org/issues/21347)
https://github.com/ruby/ruby/pull/13368

* Tidy up: Extract rsock_raise_user_specified_timeout()

* Added a note to the documentation of `Socket.tcp`

* Fix `rsock_init_inetsock` for `FAST_FALLBACK_INIT_INETSOCK_IMPL`
2025-07-17 18:15:19 +09:00
Daisuke Aritomo
b896f80598
[Bug #21512] Socket.tcp_with_fast_fallback: Pass proper addr family to getaddrinfo (#13878)
Socket.tcp_with_fast_fallback: Pass proper addr family to getaddrinfo

Addrinfo.getaddrinfo expects Socket::AF_INET or Socket::AF_INET6 as its
third argument (family). However Socket.tcp_with_fast_fallback was
incorrectly passing :ipv4 or :ipv6.

Repro:

    require 'socket'
    Socket.tcp_with_fast_fallback('example.com', 80, '127.0.0.1')

Expected behavior: Returns a Socket object
Actual: Raises unknown socket domain: ipv4 (SocketError)
2025-07-15 20:38:57 +09:00
Misaki Shioi
c45c600e22
Add open_timeout as an overall timeout option for Socket.tcp (#13368)
* Add `open_timeout` as an overall timeout option for `Socket.tcp`

[Background]
Currently, `TCPSocket.new` and `Socket.tcp` accept two kind of timeout options:
- `resolv_timeout`, which controls the timeout for DNS resolution
- `connect_timeout`, which controls the timeout for the connection attempt

With the introduction of Happy Eyeballs Version 2 (as per [RFC 8305](https://datatracker.ietf.org/doc/html/rfc8305)) in[ Feature #20108](https://bugs.ruby-lang.org/issues/20108) and [Feature #20782](https://bugs.ruby-lang.org/issues/20782), both address resolution and connection attempts are now parallelized.
As a result, the sum of `resolv_timeout` and `connect_timeout` no longer represents the total timeout duration. This is because, in HEv2, name resolution and connection attempts are performed concurrently, causing the two timeouts to overlap.

Example:
When `resolv_timeout: 200ms` and `connect_timeout: 100ms` are set:
1. An IPv6 address  is resolved after the method starts immediately (IPv4 is still being resolved).
2. A connection attempt is initiated to the IPv6 address
3. After 100ms, `connect_timeout` is exceeded. However, since `resolv_timeout` still has 100ms left, the IPv4 resolution continues.
4. After 200ms from the start, the method raises a `resolv_timeout` error.

In this case, the total elapsed time before a timeout is 200ms, not the expected 300ms (100ms + 200ms).

Furthermore, in HEv2, connection attempts are also parallelized.
It starts a new connection attempts every 250ms for resolved addresses. This makes the definition of `connect_timeout` even more ambiguous—specifically, it becomes unclear from which point the timeout is counted.

Additionally, these methods initiate new connection attempts every 250ms (Connection Attempt Delay) for each candidate address, thereby parallelizing connection attempts. However, this behavior makes it unclear from which point in time the connect_timeout is actually measured.
Currently, a `connect_timeout` is raised only after the last connection attempt exceeds the timeout.

Example:
When `connect_timeout: 100ms` is set and 3 address candidates:
1. Start a connection attempt to the address `a`
2. 250ms after step 1, start a new connection attempt to the address `b`
3. 500ms after step 1, start a new connection attempt to the address `c`
4. 1000ms after step 3 (1000ms after starting the connection to `c`, 1250ms after starting the connection to `b,` and 1500ms after starting the connection to `a`) `connect_timeout` is raised

This behavior aims to favor successful connections by allowing more time for each attempt, but it results in a timeout model that is difficult to reason about.

These methods have supported `resolv_timeout` and `connect_timeout` options even before the introduction of HEv2. However, in many use cases, it would be more convenient if a timeout occurred after a specified duration from the start of the method. Similar functions in other languages (such as PHP, Python, and Go) typically allow specifying only an overall timeout.

[Proposal]
I propose adding an `open_timeout` option to `Socket.tcp` in this PR, which triggers a timeout after a specified duration has elapsed from the start of the method.

The name `open_timeout` aligns with the existing accessor used in `Net::HTTP`.
If `open_timeout` is specified together with `resolv_timeout` and `connect_timeout`, I propose that only `open_timeout` be used and the others be ignored. While it is possible to support combinations of `open_timeout`, `resolv_timeout`, and `connect_timeout`, doing so would require defining which timeout takes precedence in which situations. In this case, I believe it is more valuable to keep the behavior simple and easy to understand, rather than supporting more complex use cases.

If this proposal is accepted, I also plan to extend `open_timeout` support to `TCPSocket.new`.

While the long-term future of `resolv_timeout` and `connect_timeout` may warrant further discussion, I believe the immediate priority is to offer a straightforward way to specify an overall timeout.

[Outcome]
If `open_timeout` is also supported by `TCPSocket.new`, users would be able to manage total connection timeouts directly in `Net::HTTP#connect` without relying on `Timeout.timeout`.
aa0f689bf4/lib/net/http.rb (L1657)

---

* Raise an exception if it is specified together with other timeout options

> If open_timeout is specified together with resolv_timeout and connect_timeout, I propose that only open_timeout be used and the others be ignored.

Since this approach may be unclear to users, I’ve decided to explicitly raise an `ArgumentError` if these options are specified together.

* Add doc

* Fix: open_timeout error should be raised even if there are still addresses that have not been tried
2025-06-14 09:54:34 +09:00
Jean Boussier
580aa60051 Improve backtrace of errors raised by Socket.tcp_with_fast_fallback
[Bug #21211]

Socket errors raised from background threads are hard to track down because
their backtrace starts from the spawned thread.

To solve this we can raise a new error with the old one as `cause`.
2025-04-02 13:24:22 +02:00
Jean Boussier
ba5fb74583 Fix Socket.tcp_with_fast_fallback to be usable from a Ractor
[Bug #21179]

```
socket.rb:1046:in 'Socket::HostnameResolutionStore#get_addrinfo': can not access non-shareable objects in constant
Socket::HostnameResolutionStore::PRIORITY_ON_V6 by non-main ractor. (Ractor::IsolationError)
	from socket.rb:724:in 'block in Socket.tcp_with_fast_fallback'
	from socket.rb:720:in 'Socket.tcp_with_fast_fallback'
```
2025-03-10 22:57:44 +01:00
Misaki Shioi
1683dadb19
Do not save ResolutionError if resolution succeeds for any address family (#12678)
* Do not save ResolutionError if resolution succeeds for any address family

Socket with Happy Eyeballs Version 2 performs connection attempts and name resolution in parallel.

In the existing implementation, if a connection attempt failed for one address family while name resolution was still in progress for the other, and that name resolution later failed, the method would terminate with a name resolution error.
This behavior was intended to ensure that the final error reflected the most recent failure, potentially overriding an earlier error.

However, [Bug #21088](https://bugs.ruby-lang.org/issues/21088) made me realize that terminating with a name resolution error is unnatural when name resolution succeeded for at least one address family.

This PR modifies the behavior so that if name resolution succeeds for one address family, any name resolution error from the other is not saved.

This PR includes the following changes:

* Do not display select(2) as the system call that caused the raised error, as it is for internal processing

* Fix bug: Get errno with Socket::SO_ERROR in Windows environment with a workaround for tests not passing
2025-02-03 20:26:47 +09:00
Raul Gutierrez Segales
7ec233c85b Fix typo for private constant in Socket
Signed-off-by: Raul Gutierrez Segales <rgs@itevenworks.net>
2025-01-06 15:41:49 +09:00
nvh0412
9389a27e49 [DOC] Fix broken parameter display and see links for Socket 2024-12-16 10:07:39 +09:00
Stan Lo
e9926afb24 Fix broken links to Socket.tcp_fast_fallback=
Since it's a singleton method, it should be referenced as `Socket.tcp_fast_fallback=`,
not `Socket#tcp_fast_fallback=`.
2024-12-15 15:36:08 +09:00
Misaki Shioi
9f924e2f13
Improve APIs for Globally Enabling/Disabling fast_fallback in Socket (#12257)
This change includes the following updates:
- Added an environment variable `RUBY_TCP_NO_FAST_FALLBACK` to control enabling/disabling fast_fallback
- Updated documentation and man pages
- Revised the implementation of Socket.tcp_fast_fallback= and Socket.tcp_fast_fallback, which previously performed dynamic name resolution of constants and variables. As a result, the following performance improvements were achieved:

(Case of 1000 executions of `TCPSocket.new` to the local host)

Rehearsal -----------------------------------------
before   0.031462   0.147946   0.179408 (  0.249279)
after    0.031164   0.146839   0.178003 (  0.346935)
-------------------------------- total: 0.178003sec

            user     system      total        real
before   0.027584   0.138712   0.166296 (  0.233356)
after    0.025953   0.127608   0.153561 (  0.237971)
2024-12-14 15:51:19 +09:00
Misaki Shioi
b11287706f
Fix Connection Attempt Delay of Socket.tcp (#12291)
The following two commits fix the proper clearing of the Connection Attempt Delay in `TCPSocket.new`.

- b2f610b0ed
- 6f4efaec53

The same fix will be applied to `Socket.tcp`.
2024-12-10 00:08:56 +09:00
Misaki Shioi
d21b614bd4
[DOC] Improve Socket::tcp with Happy Eyeballs Version 2
With the introduction of Happy Eyeballs Version 2 to `Socket::tcp`, the following areas have been mainly enhanced:

- How the value specified for `connect_timeout` works
- How Socket.tcp operates with Happy Eyeballs Version 2

A description for the new option `fast_fallback` has been added in https://github.com/ruby/ruby/pull/11813.
2024-10-20 19:26:01 +09:00
Misaki Shioi
32c733f57b
[DOC] Add some descriptions for options of Socket::tcp 2024-10-07 15:28:32 +09:00
Yusuke Endoh
0f3dc2f958 Prevent warnings "the block passed to ... may be ignored" 2024-09-13 16:52:38 +09:00
Misaki Shioi
b3baa11ee9
Improve Socket.tcp (#11187)
[Feature #20646]Improve Socket.tcp

This is a proposed improvement to `Socket.tcp`, which has implemented Happy Eyeballs version 2 (RFC8305) in PR9374.

1. Background
I implemented Happy Eyeballs version 2 (HEv2) for Socket.tcp in PR9374, but several issues have been identified:

- `IO.select` waits for name resolution or connection establishment in v46w, but it does not consider the case where both events occur simultaneously when it returns a value.
  - In this case, Socket.tcp can only capture one event and needs to execute an unnecessary loop to capture the other one, calling `IO.select` one extra time.
- `IO.select` waits for both IPv6/IPv4 name resolution (in start), but when it returns a value, it doesn't consider the case where name resolution for both address families is complete.
  - In this case, `Socket.tcp` can only obtain the addresses of one address family and needs to execute an unnecessary loop obtain the other addresses, calling `IO.select` one extra time.
- The consideration for `connect_timeout` was insufficient. After initiating one or more connections, it raises a 'user specified timeout' after the `connect_timeout` period even if there were addresses that have been resolved and have not yet tried to connect.
- It does not retry with another address in case of a connection failure.
- It executes unnecessary state transitions even when an IP address is passed as the `host` argument.
- The regex for IP addresses did not correctly specify the start and end.

2. Proposal & Outcome
To overcome the aforementioned issues, this PR introduces the following changes:

- Previously, each loop iteration represented a single state transition. This has been changed to execute all processes that meet the execution conditions within a single loop iteration.
  - This prevents unnecessary repeated loops and calling `IO.select`
- Introduced logic to determine the timeout value set for `IO.select`. During the Resolution Delay and Connection Attempt Delay, the user-specified timeout is ignored. Otherwise, the timeout value is set to the larger of `resolv_timeout` and `connect_timeout`.
  - This ensures that the `connect_timeout` is only detected after attempting to connect to all resolved addresses.
- Retry with another address in case of a connection failure.
  - This prevents unnecessary repeated loops upon connection failure.
- Call `tcp_without_fast_fallback` when an IP address is passed as the host argument.
  - This prevents unnecessary state transitions when an IP address is passed.
- Fixed regex for IP addresses.

Additionally, the code has been reduced by over 100 lines, and redundancy has been minimized, which is expected to improve readability.

3. Performance
No significant performance changes were observed in the happy case before and after the improvement.
However, improvements in state transition deficiencies are expected to enhance performance in edge cases.

```ruby
require 'socket'
require 'benchmark'

Benchmark.bmbm do |x|
  x.report('fast_fallback: true') do
    30.times { Socket.tcp("www.ruby-lang.org", 80) }
  end

  x.report('fast_fallback: false') do # Ruby3.3時点と同じ
    30.times { Socket.tcp("www.ruby-lang.org", 80, fast_fallback: false) }
  end
end
```

Before:

```
~/s/build ❯❯❯ ../install/bin/ruby ../ruby/test.rb

                           user     system      total        real
fast_fallback: true    0.021315   0.040723   0.062038 (  0.504866)
fast_fallback: false   0.007553   0.026248   0.033801 (  0.533211)
```

After:

```
~/s/build ❯❯❯ ../install/bin/ruby ../ruby/test.rb

                           user     system      total        real
fast_fallback: true    0.023081   0.040525   0.063606 (  0.406219)
fast_fallback: false   0.007302   0.025515   0.032817 (  0.418680)
```
2024-07-30 12:58:31 +09:00
Nobuyoshi Nakada
d4e24021d3
Revise 9ec342e07d 2024-02-26 13:12:05 +09:00
Nobuyoshi Nakada
a0f7de814a
[Bug #20296] Fix the default assertion message 2024-02-26 12:29:23 +09:00
Misaki Shioi
9ec342e07d
Introduction of Happy Eyeballs Version 2 (RFC8305) in Socket.tcp (#9374)
* 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
2024-02-26 12:14:11 +09:00
Jean Boussier
b2fc1b054e Update BasicSocket#recv documentation on return value
Ref: https://github.com/ruby/ruby/pull/6407

[Bug #19012]

`0` is now interpreted as closed connection an not an
empty packet, as these are very rare and pretty much
useless.
2023-12-18 12:58:08 +01:00
Samuel Williams
d20bd06a97
Remove require 'io/wait' where it's no longer necessary. (#6932)
* Remove `require 'io/wait'` as it's part of core now.

* Update ruby specs using version gates.

* Add note about why it's conditional.
2022-12-15 11:37:01 +13:00
Nobuyoshi Nakada
71dd8b3caa
socket.rb - simplify check for the method 2022-12-15 00:27:47 +09:00
MSP-Greg
74995162fc
socket.rb - don't load io/wait (#6922)
See d2166c09b0 and #6036 for more context.
2022-12-14 08:57:38 +13:00
Hiroshi SHIBATA
c8bfbbc25e
Removed documentation for incomplete option about [Feature #17134] 2022-11-30 17:20:38 +09:00
Samuel Williams
ea8a7287e2
Add support for sockaddr_un on Windows. (#6513)
* 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>
2022-11-17 14:50:25 -08:00
Masaki Matsushita
0e9d56f5e7 Support timeout for Addrinfo
Addrinfo.getaddrinfo and .foreach now accepts :timeout in seconds as
a keyword argument. If getaddrinfo_a(3) is available, the timeout will be
applied for name resolution. Otherwise, it will be ignored.

Socket.tcp accepts :resolv_timeout to use this feature.

This commit is retry of 6382f5cc91.
Test was failed on Solaris machines which don't have "http" in
/etc/services. In this commit, use "ssh" instead.
2019-09-10 10:10:59 +09:00
Masaki Matsushita
c4efbf663e Revert "Support timeout for Addrinfo"
This reverts commit 6382f5cc91.
test failed on Solaris.
2019-09-09 20:34:51 +09:00
Masaki Matsushita
6382f5cc91 Support timeout for Addrinfo
Addrinfo.getaddrinfo and .foreach now accepts :timeout in seconds as
a keyword argument. If getaddrinfo_a(3) is available, the timeout will be
applied for name resolution. Otherwise, it will be ignored.

Socket.tcp accepts :resolv_timeout to use this feature.
2019-09-09 14:34:05 +09:00
nobu
131dc83145 socket.rb: protected connect_internal
* ext/socket/lib/socket.rb (Addrinfo#connect_internal): make
  protected for Addrinfo#connect_to, instead of private and send.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62449 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-02-17 07:54:52 +00:00
normal
ba5eb6458a socket: fix BasicSocket#*_nonblock buffering bugs from r58400
IO#read_nonblock and IO#write_nonblock take into account
buffered data, so the Linux-only BasicSocket#read_nonblock
and BasicSocket#write_nonblock methods must, too.

This bug was only introduced in r58400
("socket: avoid fcntl for read/write_nonblock on Linux")
and does not affect any stable release.

* ext/socket/basicsocket.c (rsock_init_basicsocket):
* ext/socket/init.c (rsock_s_recvfrom_nonblock):
* ext/socket/init.c (rsock_init_socket_init):
* ext/socket/lib/socket.rb (def read_nonblock):
* ext/socket/lib/socket.rb (def write_nonblock):
* ext/socket/rubysocket.h (static inline void rsock_maybe_wait_fd):
* test/socket/test_basicsocket.rb (def test_read_write_nonblock):
  [Feature #13362]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60496 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-10-27 23:26:48 +00:00
hsbt
6693e3e723 Fixed misspelling words.
These are detected by https://github.com/client9/misspell

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60359 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-10-22 11:27:06 +00:00
nobu
6a50386115 Add missing buf parameter to recv_nonblock doc [ci skip]
[Fix GH-1725]
From: yuuji.yaginuma <yuuji.yaginuma@gmail.com>

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60349 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-10-22 06:01:07 +00:00
normal
c32fc82d0e socket: avoid fcntl for read/write_nonblock on Linux
On platforms where MSG_DONTWAIT works reliably on all sockets
(so far, I know of Linux), we can avoid fcntl syscalls and
implement IO#write_nonblock and IO#read_nonblock in terms of the
socket-specific send and recv family of syscalls.

This avoids side effects on the socket, and also encourages
generic code to be written in cases where IO wrappers like
OpenSSL::SSL::SSLSocket are used.

Perhaps in the future, side-effect-free non-blocking I/O can
be standard on all files and OSes: https://cr.yp.to/unix/nonblock.html

* ext/socket/lib/socket.rb (read_nonblock, write_nonblock):
  Linux-specific wrapper without side effects
  [ruby-core:80780] [Feature #13362]
* test/socket/test_basicsocket.rb (test_read_write_nonblock):
  new test

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58400 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-04-19 01:08:16 +00:00
normal
abc5e8966c Socket.udp_server_sockets: use symbol proc
Symbol proc is shorter human and machine code;
and also avoids needing to name variables.

* ext/socket/lib/socket.rb (Socket.udp_server_sockets): use symbol proc

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58320 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-04-11 14:56:17 +00:00
usa
49e4df4861 Get rid of inifinity retry loop in Socket.udp_server_sockets
* ext/socket/lib/socket.rb (Socket.udp_server_sockets): remove duplicated
  addresses before passing it to ip_sockets_port0 because it causes
  Errno::EADDRINUSE and retry forever.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58293 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-04-09 16:19:37 +00:00
nobu
c9447082ec Revert r57690 except for read_nonblock
https://github.com/ruby/ruby/pull/1527#issuecomment-281867551

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57694 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-02-23 02:40:17 +00:00
nobu
d0cf19d9ed [DOC] mark up literals
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57693 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-02-23 02:11:16 +00:00
nobu
95a476c859 [DOC] keyword argument _exception_
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57692 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-02-23 02:00:28 +00:00
nobu
53b4bf3134 socket.rb: [DOC] fix nonblock methods
* ext/socket/lib/socket.rb (BasicSocket#recv_nonblock): fix
  exception class and symbol.

* ext/socket/lib/socket.rb (BasicSocket#recvmsg_nonblock): ditto.

* ext/socket/lib/socket.rb (Socket#recvfrom_nonblock): fix the
  method name.

* ext/socket/lib/socket.rb (UDPSocket#recvfrom_nonblock): both.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-02-23 01:54:13 +00:00
nobu
d5eef0301a [DOC] {read,write}_nonblock with exception: false
Update docs to reflect EOF behavior change of read_nonblock and
write_nonblock when using `exception: false`.

[Fix GH-1527]
Author:    Russell Davis <russell-stripe@users.noreply.github.com>

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57690 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-02-23 01:15:27 +00:00
normal
0514a74794 socket: use symbol proc for IO#close loops
Made possible by r56795, this reduces human and byte code size.

* ext/socket/lib/socket.rb (self.ip_sockets_port0,
  self.tcp_server_sockets_port0,
  self.tcp_server_sockets,
  self.udp_server_sockets): use symbol proc

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56867 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-11-21 23:50:25 +00:00
nobu
6394b63db9 socket.rb: remove closed checks
* ext/socket/lib/socket.rb: remove unnecessary closed checks,
  close on closed socket no longer raises an exception.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56795 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-11-15 01:39:11 +00:00
nobu
bfcb3fb3be socket.rb: kwargs
* ext/socket/lib/socket.rb (connect_{from,to}, connect): let use
  keyword arguments.

* ext/socket/lib/socket.rb (Socket.tcp): ditto.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56778 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-11-14 07:53:31 +00:00
rhe
4530a8ef7f socket: fix rdoc of UDPSocket#recvfrom_nonblock
* ext/socket/lib/socket.rb (UDPSocket#recvfrom_nonblock): [DOC] Remove
  a false statement "If _maxlen_ is omitted, its default value is
  65536." maxlen, the first parameter, cannot be omitted as the method
  signature indicates. This hasn't changed ever since it was first
  implemented.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56499 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2016-10-27 05:58:35 +00:00
hsbt
059c9c1cf3 * ext/socket/lib/socket.rb: use safe navigation operator.
[fix GH-1142] Patch by @mlarraz
* lib/drb/extservm.rb: ditto.
* lib/net/http.rb: ditto.
* lib/net/http/response.rb: ditto.
* lib/scanf.rb: ditto.
* lib/uri/generic.rb: ditto.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53111 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-12-14 08:05:35 +00:00
akr
33b832979b * ext/socket/ancdata.c: Check buffer full and ignore MSG_TRUNC flag.
buffer fullness is more robust to detect the message is too big for
  the buffer.
  AIX 7.1 recvmsg doesn't set MSG_TRUNC for rflags when MSG_PEEK is
  given.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52673 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-19 13:49:58 +00:00
normal
508b5fdd52 socket: fix recvmsg without argument
* ext/socket/ancdata.c (bsock_recvmsg_internal): grow buffer
  on unspecified maxdatlen
  [ruby-core:71517] [Bug #11701]
* ext/socket/lib/socket.rb (Socket#recvmsg): nil default for dlen
  (Socket#recvmsg_nonblock): ditto
* test/socket/test_socket.rb (test_recvmsg_udp_no_arg): new test

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52625 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-17 22:00:23 +00:00
usa
66e2139b1a * ext/socket/lib/socket.rb (Socket#recvmsg{,_nonblock}): default values
of clen must be nil.

* ext/socket/ancdata.c (bsock_sendmsg_internal): handle nil of clen.
  fixes test errors introduced at r52602.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52610 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-17 05:06:18 +00:00
usa
4b9cd6edce * ext/socket/lib/socket.rb: UNIXSocket is not always exists. fixes
install error on Windows, introduced at r52601.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52609 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-17 04:55:36 +00:00
normal
55a692bbc2 socket: update doc for recvfrom_nonblock [ci skip]
* ext/socket/lib/socket.rb (Socket#recvfrom_nonblock):
  UDPSocket#recvfrom_nonblock):
  update doc for `exception: false` and destination buffer
  [ruby-core:69542] [Feature #11229]
  [ruby-core:69543] [Feature #11242]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52608 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-17 02:29:19 +00:00
normal
8478b30267 socket: avoid exceptions in wrapper code
* ext/socket/lib/socket.rb (Socket.accept_loop): avoid exceptions
  (Socket.udp_server_recv): ditto

Exceptions for common "errors" make debug output noisy and
allocations+backtrace generation hurt performance.
[ruby-core:66385] [ruby-core:69473]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52604 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2015-11-17 01:16:25 +00:00