<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ruby.git/test/socket/test_socket.rb, branch v4.0.3</title>
<subtitle>The Ruby Programming Language</subtitle>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/'/>
<entry>
<title>Fix: Specifying 0 should cause an immediate timeout (#15641)</title>
<updated>2025-12-19T06:44:35+00:00</updated>
<author>
<name>Misaki Shioi</name>
<email>31817032+shioimm@users.noreply.github.com</email>
</author>
<published>2025-12-19T06:44:35+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=47244b0f306161f175b21f74d801882e950e18be'/>
<id>47244b0f306161f175b21f74d801882e950e18be</id>
<content type='text'>
This change fixes a bug in which specifying 0 for timeout-related options (such as the `timeout` option of `Addrinfo.getaddrinfo`) incorrectly results in an infinite wait.

(This change overwrites https://github.com/ruby/ruby/pull/15626 .)</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This change fixes a bug in which specifying 0 for timeout-related options (such as the `timeout` option of `Addrinfo.getaddrinfo`) incorrectly results in an infinite wait.

(This change overwrites https://github.com/ruby/ruby/pull/15626 .)</pre>
</div>
</content>
</entry>
<entry>
<title>`Socket.tcp` and `TCPSocket.new` raises `IO::TiemoutError` with user specified timeout (#15602)</title>
<updated>2025-12-17T06:02:26+00:00</updated>
<author>
<name>Misaki Shioi</name>
<email>31817032+shioimm@users.noreply.github.com</email>
</author>
<published>2025-12-17T06:02:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=7b5691c3b000c763faa282e1f73db96afa2ecae1'/>
<id>7b5691c3b000c763faa282e1f73db96afa2ecae1</id>
<content type='text'>
* `Socket.tcp` and `TCPSocket.new` raises `IO::TiemoutError` with user specified timeout

In https://github.com/ruby/ruby/pull/11880, `rsock_connect()` was changed to raise `IO::TimeoutError` when a user-specified timeout occurs.
However, when `TCPSocket.new` attempts to connect to multiple destinations, it does not use `rsock_connect()`, and instead raises `Errno::ETIMEDOUT` on timeout.
As a result, the exception class raised on timeout could differ depending on whether there were multiple destinations or not.

To align this behavior with the implementation of `rsock_connect()`, this change makes `TCPSocket.new` raise `IO::TimeoutError` when a user-specified timeout occurs.
Similarly, `Socket.tcp` is updated to raise `IO::TimeoutError` when a timeout occurs within the method.
(Note that the existing behavior of `Addrinfo#connect_internal`, which Socket.tcp depends on internally and which raises `Errno::ETIMEDOUT` on timeout, is not changed.)

* [ruby/net-http] Raise `Net::OpenTimeout` when `TCPSocket.open` raises `IO::TimeoutError`.

With the changes in https://github.com/ruby/ruby/pull/15602, `TCPSocket.open` now raises `IO::TimeoutError` when a user-specified timeout occurs.
This change updates #connect to handle this case accordingly.

https://github.com/ruby/net-http/commit/f64109e1cf</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
* `Socket.tcp` and `TCPSocket.new` raises `IO::TiemoutError` with user specified timeout

In https://github.com/ruby/ruby/pull/11880, `rsock_connect()` was changed to raise `IO::TimeoutError` when a user-specified timeout occurs.
However, when `TCPSocket.new` attempts to connect to multiple destinations, it does not use `rsock_connect()`, and instead raises `Errno::ETIMEDOUT` on timeout.
As a result, the exception class raised on timeout could differ depending on whether there were multiple destinations or not.

To align this behavior with the implementation of `rsock_connect()`, this change makes `TCPSocket.new` raise `IO::TimeoutError` when a user-specified timeout occurs.
Similarly, `Socket.tcp` is updated to raise `IO::TimeoutError` when a timeout occurs within the method.
(Note that the existing behavior of `Addrinfo#connect_internal`, which Socket.tcp depends on internally and which raises `Errno::ETIMEDOUT` on timeout, is not changed.)

* [ruby/net-http] Raise `Net::OpenTimeout` when `TCPSocket.open` raises `IO::TimeoutError`.

With the changes in https://github.com/ruby/ruby/pull/15602, `TCPSocket.open` now raises `IO::TimeoutError` when a user-specified timeout occurs.
This change updates #connect to handle this case accordingly.

https://github.com/ruby/net-http/commit/f64109e1cf</pre>
</div>
</content>
</entry>
<entry>
<title>test_socket.rb: Permit ProxyError for Windows</title>
<updated>2025-09-02T17:38:37+00:00</updated>
<author>
<name>Takashi Kokubun</name>
<email>takashikkbn@gmail.com</email>
</author>
<published>2025-09-02T17:38:36+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=8e1b5cba70b66a6e54f2189eb4321919b7ab776a'/>
<id>8e1b5cba70b66a6e54f2189eb4321919b7ab776a</id>
<content type='text'>
https://github.com/ruby/ruby/actions/runs/17410747983/job/49427074277
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
https://github.com/ruby/ruby/actions/runs/17410747983/job/49427074277
</pre>
</div>
</content>
</entry>
<entry>
<title>Add `open_timeout` as an overall timeout option for `Socket.tcp` (#13368)</title>
<updated>2025-06-14T00:54:34+00:00</updated>
<author>
<name>Misaki Shioi</name>
<email>31817032+shioimm@users.noreply.github.com</email>
</author>
<published>2025-06-14T00:54:34+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=c45c600e2237affa8ba62ea5b290e29a1045d483'/>
<id>c45c600e2237affa8ba62ea5b290e29a1045d483</id>
<content type='text'>
* 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`.
https://github.com/ruby/ruby/blob/aa0f689bf45352c4a592e7f1a044912c40435266/lib/net/http.rb#L1657

---

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

&gt; 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</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
* 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`.
https://github.com/ruby/ruby/blob/aa0f689bf45352c4a592e7f1a044912c40435266/lib/net/http.rb#L1657

---

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

&gt; 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</pre>
</div>
</content>
</entry>
<entry>
<title>Removed Solaris conditions from test files</title>
<updated>2025-04-02T07:24:47+00:00</updated>
<author>
<name>Hiroshi SHIBATA</name>
<email>hsbt@ruby-lang.org</email>
</author>
<published>2025-04-02T04:38:49+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=6bd5a51ab5a2b1d33fa586cb2969b25d8d68c121'/>
<id>6bd5a51ab5a2b1d33fa586cb2969b25d8d68c121</id>
<content type='text'>
We no longer execute those files with Solaris platforms.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
We no longer execute those files with Solaris platforms.
</pre>
</div>
</content>
</entry>
<entry>
<title>[Feature #21116] Extract RJIT as a third-party gem</title>
<updated>2025-02-13T09:01:03+00:00</updated>
<author>
<name>Nobuyoshi Nakada</name>
<email>nobu@ruby-lang.org</email>
</author>
<published>2025-02-13T06:59:16+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=4a67ef09ccd703047552b740431cfe15e32451f4'/>
<id>4a67ef09ccd703047552b740431cfe15e32451f4</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>Do not save ResolutionError if resolution succeeds for any address family (#12678)</title>
<updated>2025-02-03T11:26:47+00:00</updated>
<author>
<name>Misaki Shioi</name>
<email>31817032+shioimm@users.noreply.github.com</email>
</author>
<published>2025-02-03T11:26:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=1683dadb19876f0a64589bdbbcf6fff8143f78ff'/>
<id>1683dadb19876f0a64589bdbbcf6fff8143f78ff</id>
<content type='text'>
* 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</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
* 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</pre>
</div>
</content>
</entry>
<entry>
<title>Fix tests for fast_fallback (#12406)</title>
<updated>2024-12-20T09:55:26+00:00</updated>
<author>
<name>Misaki Shioi</name>
<email>31817032+shioimm@users.noreply.github.com</email>
</author>
<published>2024-12-20T09:55:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=b53a75230feb1db64320545ae45514ebd8d4c535'/>
<id>b53a75230feb1db64320545ae45514ebd8d4c535</id>
<content type='text'>
* TCPSocket.new: Close resources in ensure

* TCPSocket.new: Remove unnecessary comments

* Socket.tcp: Make assert_separately in TestSocket more readable

* Socket.tcp: Returning instead of exiting

* Socket.tcp: Close resources in ensure

* Socket.tcp: Avoid test failures on hosts that only support IPv4</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
* TCPSocket.new: Close resources in ensure

* TCPSocket.new: Remove unnecessary comments

* Socket.tcp: Make assert_separately in TestSocket more readable

* Socket.tcp: Returning instead of exiting

* Socket.tcp: Close resources in ensure

* Socket.tcp: Avoid test failures on hosts that only support IPv4</pre>
</div>
</content>
</entry>
<entry>
<title>Improve APIs for Globally Enabling/Disabling fast_fallback in Socket (#12257)</title>
<updated>2024-12-14T06:51:19+00:00</updated>
<author>
<name>Misaki Shioi</name>
<email>31817032+shioimm@users.noreply.github.com</email>
</author>
<published>2024-12-14T06:51:19+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=9f924e2f13992241c447190a9eb139bf46dcb8d9'/>
<id>9f924e2f13992241c447190a9eb139bf46dcb8d9</id>
<content type='text'>
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)</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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)</pre>
</div>
</content>
</entry>
<entry>
<title>Revise 9ec342e07df6aa5e2c2e9003517753a2f1b508fd</title>
<updated>2024-02-26T04:12:05+00:00</updated>
<author>
<name>Nobuyoshi Nakada</name>
<email>nobu@ruby-lang.org</email>
</author>
<published>2024-02-26T04:12:05+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=d4e24021d39e1f80f0055b55d91f8d5f22e15084'/>
<id>d4e24021d39e1f80f0055b55d91f8d5f22e15084</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
</feed>
