1324 Commits
Author SHA1 Message Date
Hiroshi SHIBATAandClaude Opus 5.5 021446fa21 Fix the timeout of getaddrinfo with a nil host or service
Building the error message from a NULL pointer raised ArgumentError instead of IO::TimeoutError.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 08:42:54 +09:00
Hiroshi SHIBATAandClaude Opus 5.5 47d566434f mswin: Resolve hostnames in a dedicated thread
Without pthread, mswin fell back to GETADDRINFO_IMPL 1, which ignores the timeout of Addrinfo.getaddrinfo and lets neither Timeout, Thread#kill nor Thread#raise stop the caller until getaddrinfo(3) returns. Start the resolver thread with _beginthreadex(3) so mswin takes GETADDRINFO_IMPL 2 as the pthread platforms do. MinGW stays on GETADDRINFO_IMPL 1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 08:42:54 +09:00
Hiroshi SHIBATAandClaude Opus 5.5 a98386e422 Drop the unused thread handle from the resolver thread creation
No caller reads the pthread_t, so raddrinfo_thread_create() no longer takes one, and a non-pthread implementation can sit behind it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 08:42:54 +09:00
Hiroshi SHIBATAandClaude Opus 5.5 349d9d65bc Initialize the fast fallback waiter fd before anything can raise
An invalid open_timeout raised before the waiter was assigned, so the cleanup closed fd 0 left by memset and took the process's stdin with it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 14:16:14 +09:00
Hiroshi SHIBATAandClaude Opus 5.5 09053cae8a Clamp the length given to Winsock send() to int
Winsock takes the length as int, so a String of 2GiB or more had its length truncated. The caller now sees a short write, as BasicSocket#send already reports one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:07:39 +09:00
William T. NelsonandClaude Opus 5.5 f33766720c Socket.tcp_with_fast_fallback: Fix typo in getaddrinfo family
ADDRESS_FAMILIES[:family_name] used the Symbol :family_name as the key
instead of the local variable family_name, so the address family was
always nil. This is a follow-up to b896f80598 [Bug #21512].

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 23:19:44 +02:00
Douglas Eichelberger 44f7c6b00d Join getaddrinfo and getnameinfo threads before fork
A getaddrinfo thread calls getaddrinfo(3) inside rb_thread_prevent_fork,
but on glibc its thread exit takes the resolver configuration lock again
after the thread has released the fork lock. A fork that lands then
leaves the child with that lock held, and every later name lookup in the
child blocks forever. getnameinfo(3) attaches the same resolver state,
even for a name in /etc/hosts, and its thread ran outside
rb_thread_prevent_fork altogether.

Make the lookup threads joinable and have fork join any that may still
be exiting. As a lookup thread finishes, still inside
rb_thread_prevent_fork, it swaps itself into a single slot with an
atomic exchange and joins the thread it displaced, which has usually
exited by then, and rb_thread_acquire_fork_lock joins whatever is left
in the slot. Once lookups settle, at most one finished thread is left
unjoined. The slot holds pthread_t as a pointer, with NULL for empty,
which assumes pthread_t is scalar and never 0.

getnameinfo threads now run within rb_thread_prevent_fork and register
as they exit, as getaddrinfo threads do, and where getnameinfo runs
without a helper thread it is called within rb_thread_prevent_fork too.
So fork also waits for a reverse lookup in progress, as it already did
for a forward one. raddrinfo_pthread_create now always creates joinable
threads, which drops its pthread_detach fallback for platforms without
pthread_attr_setdetachstate.

The slot is kept across fork, so every fork path that keeps running
Ruby code has to take the fork lock. On the BSDs, Process.daemon forks
with daemon(3) and did not take it, so the daemon would inherit the
registered thread, and its next fork would abort in pthread_join with
ESRCH. Take and release the fork lock around daemon(3) as rb_fork_ruby
does. daemon(3) can fail in the child as well as in the parent, so
compare pids to tell which process returned.

[Bug #22406]
2026-10-14 10:46:00 +02:00
Tiago Cardoso 36f2a8e807 [Feature #13677] Add host to addrinfo resolution errors
hostname is added as a suffix to getaddrinfo error messages. for
example, a "name or service not known" error message becomes "name or
service not known for `invalidthost.com`.
2026-10-12 14:33:34 +02:00
Hiroshi SHIBATAandClaude Opus 5.5 d2ec641fb4 Use rb_len_t for String and Array lengths in ext/socket
The lengths passed to recv(2), send(2) and gethostname(2), and the lengths of sockaddr, are left as they are.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 16:45:25 +09:00
Hiroshi SHIBATAandClaude Opus 5.5 4e182fecac Remove Debian GNU/kFreeBSD support
Debian GNU/kFreeBSD left the official releases after Debian 7 and was removed from debian-ports in 2023. The k*bsd*-gnu pattern also matched GNU/kNetBSD, which was abandoned long before that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 09:00:26 +09:00
Hiroshi SHIBATAandClaude Opus 5 ffd032a60b Report the IPv4 resolution error after EAI_ADDRFAMILY for IPv6
EAI_ADDRFAMILY left the IPv6 result looking successful, so a later IPv4 resolution error was not recorded and TCPSocket.new raised Socket::ResolutionError with error_code 0. When the IPv6 notification failed, EAI_ADDRFAMILY was recorded instead and hid the IPv4 error.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-01 10:51:19 +09:00
Hiroshi SHIBATAandClaude Opus 5 cfa8947403 Keep the getaddrinfo result when the resolver notification fails
The errno of the failed write(2) overwrote err, so the main thread took it for an EAI code, discarding addresses that had been resolved or raising with an unrelated message.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-01 10:51:19 +09:00
Hiroshi SHIBATAandClaude Opus 5 7a770e26b2 Stop reading the resolver pipe on EOF and errors
The loop only left on EAGAIN, so EOF or a read error other than EINTR spun forever while holding the GVL.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-01 10:51:19 +09:00
Hiroshi SHIBATAandClaude Opus 5 903930335d Watch fd 0 when it is the only connection attempt
When stdin is closed, a socket can get fd 0, and nfds stayed 0 if it was the only fd to wait for, so select never reported the connection.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-29 16:11:06 +09:00
Hiroshi SHIBATAandClaude Opus 5 4fbebba3da Forget the connection attempt fd when getsockopt fails
The fd was closed but left in connection_attempt_fds, so it was passed to the next select and closed again in the cleanup, possibly after the number had been reused.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-29 16:11:06 +09:00
Hiroshi SHIBATAandClaude Opus 5 b72d2fec2c Don't skip the next connection attempt after a failed one
remove_connection_attempt_fd shifts the remaining fds down, so advancing the index skipped the fd moved into the current slot. A connection that had already succeeded could go unnoticed until the next select, and a new attempt was started meanwhile.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-29 16:11:06 +09:00
Hiroshi SHIBATAandClaude Opus 5 009103a39f Read has_syserr under the lock
The main thread polls has_syserr on every loop while the resolver thread may be setting it, so read it with the lock the resolver thread holds. Once it is seen set, err and ai were written before it and can be read as before.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-29 16:07:31 +09:00
Hiroshi SHIBATAandClaude Opus 5 b42fdd9ef4 Close the resolver notification pipe under the lock
The resolver thread checks notify and writes to it while holding the lock. Closing it outside the lock let the thread write a byte to an unrelated file that had reused the fd number.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-29 16:07:31 +09:00
Samuel Williams 11f6d3d68b Flush buffered data in BasicSocket#close_write before shutdown. (#18900)
When a socket has buffered output (`sync == false`) and `#close_write` is
called, the write side was shut down via `shutdown(SHUT_WR)` without first
flushing the buffer. This had two bad consequences:

- the buffered bytes were silently dropped (never delivered to the peer);
- a subsequent `#close` tried to flush the still-populated write buffer
  into the now `shutdown(SHUT_WR)` socket and raised `Errno::EPIPE`.

Flush the buffer before shutting down the write side, matching the
write-only branch (which flushes via `rb_io_close`) and the non-socket
`IO#close_write` path. `IO#close_write` for a plain `IO` wrapping a socket
fd is fixed in the same way.

Assisted-By: devx/2c064143-8655-4631-a7cd-6395bb241bdc
2026-09-18 03:36:26 +00:00
Hiroshi SHIBATAandClaude Opus 5 d888c457c2 Rename allocate_fast_fallback_getaddrinfo_hints
It only fills in the given hints and allocates nothing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 15:06:08 +09:00
Hiroshi SHIBATAandClaude Opus 5 f4433d6a40 Don't crash on non-Hash delay or error in test_mode_settings
Only test_mode_settings itself was checked to be a Hash, and its delay and error values were passed to rb_hash_aref as they were.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 15:06:08 +09:00
Hiroshi SHIBATAandClaude Opus 5 3b64ab47d0 Convert the fast fallback test delay with NUM2LONG
The delay in `test_mode_settings` was stored as a raw VALUE, so a delay of n milliseconds slept for 2n+1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 11:56:09 +09:00
Hiroshi SHIBATAandClaude Opus 5 f1af5e5d90 Wait for the exceptfds of a connecting socket on Windows
Winsock reports a failed non-blocking connect(2) only through the
exceptfds of select(2), which IO#wait_writable never asks for.  So
Addrinfo#connect_internal kept waiting on a socket whose connection had
already been refused, and burned the whole connect_timeout before
raising Errno::ETIMEDOUT instead of the real error.

Ask for the priority event on Windows alone.  The M:N thread scheduler
refuses any wait carrying another event, so requesting it where it
cannot fire would take the wait off that scheduler for nothing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 19:50:19 +09:00
Nobuyoshi Nakada b51ae934f7 [Feature #22215] Remove vm_core dependency from gc header
Keep `internal/gc.h` usable without VM-private definitions so bundled
extensions do not inherit `vm_core.h` dependencies.
2026-08-07 09:59:15 +09:00
Hiroshi SHIBATAandClaude Fable 5 82294a714f [Bug #22223] Check SO_ERROR after waiting for nonblocking connect
Darwin 27 answers the retry connect(2) on a refused nonblocking socket
with EISCONN, so the retry idiom in Addrinfo#connect_internal returned
an unconnected socket. SO_ERROR still holds the real error, so consult
it after wait_writable, as wait_connectable() in init.c already does.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-06 15:23:21 +09:00
Nobuyoshi Nakada e0fc139e1b [Misc #22206] Derive generated dependencies from Makefile targets 2026-07-23 00:54:12 +09:00
Nobuyoshi Nakada 7d4461e162 [Misc #22206] Generate dependencies without compiler builds
Replace `tool/update-deps` with a Ruby source scanner so dependency
updates no longer require GNU make, a configured build, or compiler
preprocessor output.

Keep compact source mappings and scanner declarations in dependency
files, and expand complete rules into the build directory.  Avoid the
temporary fixture headers required by the compiler-driven prototype.

Use the generated rules from GNU make, BSD make, and NMake builds.
Support out-of-tree and read-only source trees, and retain expanded
dependencies shipped in release archives when baseruby is unavailable.
2026-07-23 00:04:47 +09:00
Hiroshi SHIBATAandClaude Fable 5 630f604dc4 Remove unreachable require of io/wait in socket.rb
IO#wait_writable is defined in core since Ruby 3.2, so this guard
never requires io/wait when running on the ruby built from this tree.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 18:45:52 +09:00
Nobuyoshi Nakada 403200c900 Inspect socket credentials only when the structures are defined
Specifically, on macOS, while `SCM_CREDS` is defined, the definition
of `struct cmsgcred` is disabled.
2026-07-21 17:23:43 +09:00
Nobuyoshi Nakada b9a50a0b81 Bound the hostname terminator search
Search only the gethostname buffer for its terminator so resizing the
Ruby string does not read beyond the returned data.
2026-07-15 13:28:39 +09:00
Matt Valentine-House 5465dca954 Prefer rb_sym2str over rb_id2str(SYM2ID) 2026-06-24 22:15:52 +01:00
John HawthornandLuke Gruber daffaaee73 Mark most TypedData types as THREAD_SAFE_FREE
Set RUBY_TYPED_THREAD_SAFE_FREE on TypedData types whose dfree function
is trivially safe, and only frees its own memory

Types not yet marked as THREAD_SAFE_FREE:
- id2ref_tbl_type: sets the process-global id2ref_tbl to NULL.
- mutex_data_type: unlinks itself from another thread's keeping_mutexes list.
- autoload_data_type: deletes nodes from a shared intrusive list.
- autoload_const_type: deletes itself from a shared list.
- rb_cont_data_type: mutates the shared fiber pool and the global first_jit_cont list.
- rb_fiber_data_type: delegates to cont_free.
- FiberPoolDataType: mutates shared fiber pool free-lists.
- ractor_data_type: reconfigures global VM event-hook flags and call caches.
- exported_object_registry: frees a global table under the VM lock.
- rb_box_data_type (Box::Entry): unlinks classext from other live class and module objects.
- box_ext_cleanup_type: dereferences another String object and calls unlink.
- monitor_data_type: uses the default free, so the flag has no effect.

Co-authored-by: Luke Gruber <luke.gruber@shopify.com>
2026-06-23 13:30:26 -07:00
Nobuyoshi Nakada 283bd19d15 [Feature #17944] Remove no longer used functions 2026-06-12 10:08:43 +09:00
Nobuyoshi Nakada 221c7c6644 [Feature #17944] Remove deprecated socket methods
These methods have been deprecated since nine years ago.
2026-06-11 20:12:59 +09:00
Nobuyoshi Nakada 2a5394cee7 Dump FreeBSD socket credential data wholely 2026-06-05 22:38:34 +09:00
Nobuyoshi Nakada f78cd18c91 Reduce unnecessary intermediate strings
`"%" PRIsVALUE` just copies/appends the corresponding argument as a
string.
2026-05-30 22:34:14 +09:00
Misaki Shioi 8601f5a42e Fix reading freed memory in rb_getaddrinfo 2026-05-20 09:13:51 +09:00
Nobuyoshi Nakada c091c186e4 Fix thread leaks
Wait for terminated threads to finish.
2026-04-09 14:19:02 +09:00
Jean Boussier 6cd4549060 Optimize File.join common use case
`File.join` is a hotspot for common libraries such as Zeitwerk
and Bootsnap. It has a fairly flexible signature, but 99% of
the time it's called with just two (or a small number of) UTF-8 strings.

If we optimistically optimize for that use case we can cut down a large
number of type and encoding checks, significantly speeding up the method.

The one remaining expensive check we could try to optimize is `str_null_check`.
Given it's common to use the same base string for joining, we could memoize it.
Also we could precompute it for literal strings.

```
compare-ruby: ruby 4.1.0dev (2026-01-17T14:40:03Z master 00a3b71eaf) +PRISM [arm64-darwin25]
built-ruby: ruby 4.1.0dev (2026-01-18T12:10:38Z spedup-file-join 069bab58d4) +PRISM [arm64-darwin25]
warming up....

|              |compare-ruby|built-ruby|
|:-------------|-----------:|---------:|
|two_strings   |      2.475M|    9.444M|
|              |           -|     3.82x|
|many_strings  |    551.975k|    2.346M|
|              |           -|     4.25x|
|array         |    514.946k|  522.034k|
|              |           -|     1.01x|
|mixed         |    621.236k|  633.189k|
|              |           -|     1.02x|
```
2026-01-18 16:31:31 +01:00
Misaki Shioi 3fe2ebf8e4 Remove unnecessary comparison from is_local_port_fixed (#15757)
Simplify the conditions:
- Return false if the port is 0 or a negative number
- Return true if the port is a positive number
2025-12-28 17:23:50 +09:00
Misaki Shioi a8c3d5e127 Fix: Do not fast_fallback if local_port is explicitly specified (#15732)
`fast fallback` cannot be used with explicitly specified local port,
because concurrent binds to the same `local_host:local_port`
can raise `Errno::EADDRINUSE`.

This issue is more likely to occur on hosts with `IPV6_V6ONLY` disabled,
because IPv6 binds can also occupy IPv4-mapped IPv6 address space.
2025-12-27 18:26:56 +09:00
Misaki Shioi 47244b0f30 Fix: Specifying 0 should cause an immediate timeout (#15641)
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 .)
2025-12-19 15:44:35 +09:00
Misaki Shioi 42d66b894c Fix: Do not check open_timeout twice (#15626) 2025-12-19 12:12:12 +09:00
Misaki Shioi 54d3945ee5 Add host information to timeout error messages in TCPSocket.new and Socket.tcp (#15582)
This change adds host information to the error messages shown when a timeout occurs while passing timeout options to `TCPSocket.new` or `Socket.tcp`, for improved usability.
(When the `fast_fallback option` is enabled, there may be multiple possible destinations, so the host name is shown instead of an IP address.)

As part of this change, the error messages in `Addrinfo.getaddrinfo` and `Addrinfo#connect_internal`, both of which are used by `Socket.tcp`, have also been improved in the same way.
2025-12-17 16:16:32 +09:00
Misaki Shioi 7b5691c3b0 Socket.tcp and TCPSocket.new raises IO::TiemoutError with user specified timeout (#15602)
* `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
2025-12-17 15:02:26 +09:00
Misaki Shioi 74a365310c Fix: Recalculate the timeout duration considering open_timeout (#15596)
This change updates the behavior so that, when there is only a single destination and `open_timeout` is specified, the remaining `open_timeout` duration is used as the connection timeout.
2025-12-17 11:11:39 +09:00
Misaki Shioi 2b1a9afbfb Fix: Do not pass negative timeout to Addrinfo#connect_internal (#15578)
This change fixes a bug where, with `Socket.tcp`’s `fast_fallback option` disabled, specifying `open_timeout` could unintentionally pass a negative value to `Addrinfo#connect_internal`, `causing an ArgumentError`.

```
❯ ruby -rsocket -e 'p Socket.tcp("localhost", 9292, open_timeout: 1, fast_fallback: false)'
/Users/misaki-shioi/src/install/lib/ruby/4.0.0+0/socket.rb:64:in 'IO#wait_writable': time interval must not be negative (ArgumentError)

          sock.wait_writable(timeout) or
                             ^^^^^^^
	from /Users/misaki-shioi/src/install/lib/ruby/4.0.0+0/socket.rb:64:in 'Addrinfo#connect_internal'
	from /Users/misaki-shioi/src/install/lib/ruby/4.0.0+0/socket.rb:141:in 'Addrinfo#connect'
	from /Users/misaki-shioi/src/install/lib/ruby/4.0.0+0/socket.rb:964:in 'block in Socket.tcp_without_fast_fallback'
	from /Users/misaki-shioi/src/install/lib/ruby/4.0.0+0/socket.rb:231:in 'Array#each'
	from /Users/misaki-shioi/src/install/lib/ruby/4.0.0+0/socket.rb:231:in 'Addrinfo.foreach'
	from /Users/misaki-shioi/src/install/lib/ruby/4.0.0+0/socket.rb:945:in 'Socket.tcp_without_fast_fallback'
	from /Users/misaki-shioi/src/install/lib/ruby/4.0.0+0/socket.rb:671:in 'Socket.tcp'
	from -e:1:in '<main>'
```
2025-12-16 19:52:45 +09:00
Luke Gruber 98ab418fed Revert "Fix Socket.tcp cleanup after Thread#kill (#15131)" (#15565)
This reverts commit 3038286a4b.

The following CI failure scared me:
https://github.com/ruby/ruby/actions/runs/20241051861/job/58108997049

```
  1) Timeout:
  TestResolvDNS#test_multiple_servers_with_timeout_and_truncated_tcp_fallback
```

Since it could be related, I'm reverting this for now.
2025-12-15 17:07:15 -05:00
Luke Gruber 3038286a4b Fix Socket.tcp cleanup after Thread#kill (#15131)
Socket.tcp launches ruby threads to resolve hostnames, and those threads
communicate through a queue implemented with `IO.pipe`. When the thread
that called `Socket.tcp` is killed, the resolver threads still try to
communicate through the pipe even though it may be closed. The method
`Socket.tcp_with_fast_fallback` tries to deal with this by killing the
threads in an ensure block, and then closing the pipe. However, calling
`Thread#kill` is not a blocking operation, it only sets a flag on the
thread telling it to raise during the next interrupt. The thread needs
to be joined to ensure it is terminated. The following script
demonstrates the issue:

```ruby
require "socket"

ts = []
5.times do
  ts << Thread.new do
    loop do
      1_000.times do |i|
        puts "#{i}"
        t = Thread.new do
          Socket.tcp("ruby-lang.org", 80)
        end
        sleep 0.001
        t.kill
      end
    end
  end
end
ts.each(&:join)
```

output:
```
/Users/luke/workspace/ruby-dev/ruby-build-debug/.ext/common/socket.rb:1019:in 'IO#write': closed stream (IOError)
	from /Users/luke/workspace/ruby-dev/ruby-build-debug/.ext/common/socket.rb:1019:in 'IO#putc'
	from /Users/luke/workspace/ruby-dev/ruby-build-debug/.ext/common/socket.rb:1019:in 'block in Socket::HostnameResolutionResult#add'
	from /Users/luke/workspace/ruby-dev/ruby-build-debug/.ext/common/socket.rb:1017:in 'Thread::Mutex#synchronize'
	from /Users/luke/workspace/ruby-dev/ruby-build-debug/.ext/common/socket.rb:1017:in 'Socket::HostnameResolutionResult#add'
	from /Users/luke/workspace/ruby-dev/ruby-build-debug/.ext/common/socket.rb:980:in 'Socket.resolve_hostname'
	from /Users/luke/workspace/ruby-dev/ruby-build-debug/.ext/common/socket.rb:719:in 'block (2 levels) in Socket.tcp_with_fast_fallback'
/Users/luke/workspace/ruby-dev/ruby-build-debug/.ext/common/socket.rb:1019:in 'IO#write': closed stream (IOError)
	from /Users/luke/workspace/ruby-dev/ruby-build-debug/.ext/common/socket.rb:1019:in 'IO#putc'
	from /Users/luke/workspace/ruby-dev/ruby-build-debug/.ext/common/socket.rb:1019:in 'block in Socket::HostnameResolutionResult#add'
	from /Users/luke/workspace/ruby-dev/ruby-build-debug/.ext/common/socket.rb:1017:in 'Thread::Mutex#synchronize'
	from /Users/luke/workspace/ruby-dev/ruby-build-debug/.ext/common/socket.rb:1017:in 'Socket::HostnameResolutionResult#add'
	from /Users/luke/workspace/ruby-dev/ruby-build-debug/.ext/common/socket.rb:978:in 'Socket.resolve_hostname'
	from /Users/luke/workspace/ruby-dev/ruby-build-debug/.ext/common/socket.rb:719:in 'block (2 levels) in Socket.tcp_with_fast_fallback'
```
2025-12-15 11:48:34 -05:00
Nobuyoshi Nakada beb85e7eee [Bug #21705] Fix segfaults on Windows
It should check the type of the argument and coercion before
converting the encoding.
2025-11-23 13:55:15 +09:00