summaryrefslogtreecommitdiff
path: root/ext/socket
AgeCommit message (Collapse)Author
2025-12-19Fix: Specifying 0 should cause an immediate timeout (#15641)Misaki Shioi
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-19Fix: Do not check open_timeout twice (#15626)Misaki Shioi
2025-12-17Add host information to timeout error messages in `TCPSocket.new` and ↵Misaki Shioi
`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`Socket.tcp` and `TCPSocket.new` raises `IO::TiemoutError` with user ↵Misaki Shioi
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-17Fix: Recalculate the timeout duration considering `open_timeout` (#15596)Misaki Shioi
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-16Fix: Do not pass negative timeout to Addrinfo#connect_internal (#15578)Misaki Shioi
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-15Revert "Fix Socket.tcp cleanup after Thread#kill (#15131)" (#15565)Luke Gruber
This reverts commit 3038286a4bf7832f1c42c8cc9774ee6ff19876fc. 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-15Fix Socket.tcp cleanup after Thread#kill (#15131)Luke Gruber
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-11-23[Bug #21705] Fix segfaults on WindowsNobuyoshi Nakada
It should check the type of the argument and coercion before converting the encoding.
2025-11-19Win32: Drop support for older than MSVC 9.0/_MSC_VER 1500Nobuyoshi Nakada
Visual C++ 2008 (9.0): - _MSC_VER: 1500 - MSVCRT_VERSION: 90
2025-11-19Win32: Drop support for older than MSVC 8.0/_MSC_VER 1400Nobuyoshi Nakada
Visual C++ 2005 (8.0): - _MSC_VER: 1400 - MSVCRT_VERSION: 80
2025-11-13ext/socket: Set raddrinfo thread as detached before thread start (#15142)Luke Gruber
We were seeing segfaults when calling `pthread_detach`. Apparently in some versions of glibc there is a race between when this is called (usually right after starting a thread) and a short-lived thread's shutdown routine. The bug has been reported to glibc: https://sourceware.org/bugzilla/show_bug.cgi?id=19951 I haven't been able to reproduce it on my Linux desktop but apparently it's easier to reproduce on certain kinds of servers. As a workaround, we can set the thread's detach state before thread start. I don't know of a platform that doesn't have `pthread_attr_setdetachstate`, but to be safe we check for it in `extconf.rb` and use `pthread_detach` as a backup if it isn't available. Fixes [Bug #21679]
2025-11-07update referenced filenames from namespace to boxSatoshi Tagomori
2025-11-06[DOC] Stop documentation for internalsNobuyoshi Nakada
Stop documentation for undocumented private constants and private class methods. And align private method definition styles. Also `Socket.tcp_with_fast_fallback` looks private as well as `Socket.tcp_without_fast_fallback`.
2025-11-06Dispatch by platform at loadNobuyoshi Nakada
`RUBY_PLATFORM` should be invariant within the same process.
2025-10-23[DOC] Tweaks for TCPSocket.newniku
2025-09-13Remove an unused expressionNobuyoshi Nakada
2025-09-13Get rid of `strcpy`Nobuyoshi Nakada
On OpenBSD: ``` ld: warning: namespace.c:731(namespace.o:(rb_namespace_local_extension)): warning: strcpy() is almost always misused, please use strlcpy() ```
2025-08-25Cast down to socklen_t explicitly in rb_getnameinfoJean Boussier
Similar to 19f3793a4bd6974cd66cc058fc6d2ae733337745 Fixes: ``` ../../../ext/socket/raddrinfo.c:755:60: warning: implicit conversion loses integer precision: 'size_t' (aka 'unsigned long') to 'socklen_t' (aka 'unsigned int') [-Wshorten-64-to-32] 755 | return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); | ~~~~~~~~~~~ ^~~~~~~ ../../../ext/socket/raddrinfo.c:755:45: warning: implicit conversion loses integer precision: 'size_t' (aka 'unsigned long') to 'socklen_t' (aka 'unsigned int') [-Wshorten-64-to-32] 755 | return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); | ~~~~~~~~~~~ ^~~~~~~ ```
2025-08-25Cast down to `socklen_t` explicitlyNobuyoshi Nakada
2025-08-20Avoid spawning thread for trivial getnameinfo callsJohn Hawthorn
When calling getnameinfo we spawn a thread because it may do a slow, blocking reverse-DNS lookup. Spawning a thread is relatively fast (~20µs on my Linux machine) but still an order of magnitude slower than when getnameinfo is simply translating to a numeric IP or port, which, at least in my tests on Linux, doesn't even make a syscall. This commit adds a fast path for when reverse DNS isn't required: either host isn't being fetched or NI_NUMERICHOST is set AND either the service name isn't required or NI_NUMERICSERV is set. The service name should only need to read /etc/services, which should be fast-ish, but is still I/O so I kept the existing behaviour (it could be on a network fs I guess). I tested with: s = TCPSocket.open("www.ruby-lang.org", 80) 500_000.times { Socket.unpack_sockaddr_in(s.getpeername) } Before: 12.935s After: 0.338s
2025-07-23Prevent a warning: old-style function definitionYusuke Endoh
ipsocket.c:57:1: warning: old-style function definition [-Wold-style-definition] 57 | current_clocktime() | ^~~~~~~~~~~~~~~~~
2025-07-17Flag rsock_raise_user_specified_timeout() as NORETURN (#13928)Daisuke Aritomo
This suppresses this warning: ../../../ext/socket/ipsocket.c: In function ‘rsock_raise_user_specified_timeout’: ../../../ext/socket/ipsocket.c:30:1: warning: function might be candidate for attribute ‘noreturn’ [-Wsuggest-attribute=noreturn] 30 | rsock_raise_user_specified_timeout() | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2025-07-17Declare `rsock_raise_user_specified_timeout` as noreturnNobuyoshi Nakada
2025-07-17[Feature #21347] Add `open_timeout` as an overall timeout option for ↵Misaki Shioi
`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-15[Bug #21512] Socket.tcp_with_fast_fallback: Pass proper addr family to ↵Daisuke Aritomo
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-11Update dependencies for addition of set.h to public headersJeremy Evans
2025-07-11Fix `heap-use-after-free` in `rb_getaddrinfo` (#13856)Misaki Shioi
This change addresses the following ASAN error: ``` ==1973462==ERROR: AddressSanitizer: heap-use-after-free on address 0x5110002117dc at pc 0x749c307c8a65 bp 0x7ffc3af331d0 sp 0x7ffc3af331c8 READ of size 4 at 0x5110002117dc thread T0 #0 0x749c307c8a64 in rb_getaddrinfo /tmp/ruby/src/trunk_asan/ext/socket/raddrinfo.c:564:14 #1 0x749c307c8a64 in rsock_getaddrinfo /tmp/ruby/src/trunk_asan/ext/socket/raddrinfo.c:1008:21 #2 0x749c307cac48 in rsock_addrinfo /tmp/ruby/src/trunk_asan/ext/socket/raddrinfo.c:1049:12 #3 0x749c307b10ae in init_inetsock_internal /tmp/ruby/src/trunk_asan/ext/socket/ipsocket.c:62:23 #4 0x562c5b2e327e in rb_ensure /tmp/ruby/src/trunk_asan/eval.c:1080:18 #5 0x749c307aafd4 in rsock_init_inetsock /tmp/ruby/src/trunk_asan/ext/socket/ipsocket.c:1318:12 #6 0x749c307b3b78 in tcp_svr_init /tmp/ruby/src/trunk_asan/ext/socket/tcpserver.c:39:12 ``` Fixed to avoid accessing memory that has already been freed after calling `free_getaddrinfo_arg`.
2025-07-10Fix timeout in Addrinfo.getaddrinfo to actually take effect (#13803)Misaki Shioi
[Bug #21506] Fix timeout in Addrinfo.getaddrinfo to actually take effect This change fixes an issue where the timeout option in `Addrinfo.getaddrinfo` was not functioning as expected. It also addresses a related issue where specifying `fast_fallback: false` with `resolv_timeout` for `Socket.tcp` and`TCPSocket.new` would have no effect. The timeout option was originally introduced in: https://github.com/ruby/ruby/commit/6382f5cc91ac9e36776bc854632d9a1237250da7 However, the value was noy used in current implementation: https://github.com/ruby/ruby/blob/3f0e0d5c8bf9046aee7f262a3f9a7524d51aaf3e/ext/socket/raddrinfo.c#L1282-1308 Therefore, even if a timeout is specified and the duration elapses during name resolution, nothing happens. This is clearly not the intended behavior. `Addrinfo.getaddrinfo` has been made interruptible as of Feature #19965. This change uses that feature to interrupt name resolution when the specified timeout period elapses, raising a user-specified timeout error. The timeout can be specified in milliseconds. The same issue affects `Socket.tcp` and `TCPSocket.new` when `resolv_timeout` is set along with `fast_fallback: false`. `resolv_timeout` was introduced in the following commits: https://github.com/ruby/ruby/commit/6382f5cc91ac9e36776bc854632d9a1237250da7 https://github.com/ruby/ruby/commit/511fe23fa2bdf1f17faa91e0558be47b5bb62b2a The reason is that with `fast_fallback: false`, these methods internally call the same `rsock_getaddrinfo()` as `Addrinfo.getaddrinfo`. This change addresses that as well.
2025-07-03Suppress a warning in code for SOCKS5Nobuyoshi Nakada
2025-07-02[Bug #21497] [ruby/socket]: add full prototypeZ. Liu
otherwise, gcc 15 will complain: > init.c:573:19: error: too many arguments to function ‘Rconnect’; expected 0, have 3 > 573 | return (VALUE)Rconnect(arg->fd, arg->sockaddr, arg->len); > | ^~~~~~~~ ~~~~~~~ > In file included from init.c:11: > rubysocket.h:294:5: note: declared here > 294 | int Rconnect(); > | ^~~~~~~~ > sockssocket.c:33:9: error: too many arguments to function ‘SOCKSinit’; expected 0, have 1 > 33 | SOCKSinit("ruby"); > | ^~~~~~~~~ ~~~~~~ > In file included from sockssocket.c:11: > rubysocket.h:293:6: note: declared here > 293 | void SOCKSinit(); > | ^~~~~~~~~ Signed-off-by: Z. Liu <zhixu.liu@gmail.com>
2025-06-14Add `open_timeout` as an overall timeout option for `Socket.tcp` (#13368)Misaki Shioi
* 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 > 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 Notes: Merged-By: shioimm <shioi.mm@gmail.com>
2025-06-05Suppress warnings by gcc-13 with `-Og`Nobuyoshi Nakada
2025-06-04Implement write barrier for addrinfoDaniel Colson
`rb_addrinfo_t` has `VALUE inspectname` and `VALUE canonname`, so this triggers the write barrier for those. The `AddrInfo` wasn't readily available where we need to call `RB_OBJ_WRITE`, so this involves passing `self` around a bit. Notes: Merged: https://github.com/ruby/ruby/pull/13503
2025-05-20Make Addrinfo objects Ractor shareableAaron Patterson
Allow Addrinfo objects to be shared among Ractors. Addrinfo objects are already immutable, so I think it's safe for us to tag them as RUBY_TYPED_FROZEN_SHAREABLE shareable too. Notes: Merged: https://github.com/ruby/ruby/pull/13388
2025-05-11Update common.mk dependenciesYusuke Endoh
2025-05-11namespace on readSatoshi Tagomori
2025-05-03Fix `heap-use-after-free` in `free_fast_fallback_getaddrinfo_entry` (#13231)Misaki Shioi
This change addresses the following ASAN error: ``` ==36597==ERROR: AddressSanitizer: heap-use-after-free on address 0x512000396ba8 at pc 0x7fcad5cbad9f bp 0x7fff19739af0 sp 0x7fff19739ae8 WRITE of size 8 at 0x512000396ba8 thread T0 [643/756] 36600=optparse/test_summary #0 0x7fcad5cbad9e in free_fast_fallback_getaddrinfo_entry /home/runner/work/ruby-dev-builder/ruby-dev-builder/ext/socket/raddrinfo.c:3046:22 #1 0x7fcad5c9fb48 in fast_fallback_inetsock_cleanup /home/runner/work/ruby-dev-builder/ruby-dev-builder/ext/socket/ipsocket.c:1179:17 #2 0x7fcadf3b611a in rb_ensure /home/runner/work/ruby-dev-builder/ruby-dev-builder/eval.c:1081:5 #3 0x7fcad5c9b44b in rsock_init_inetsock /home/runner/work/ruby-dev-builder/ruby-dev-builder/ext/socket/ipsocket.c:1289:20 #4 0x7fcad5ca22b8 in tcp_init /home/runner/work/ruby-dev-builder/ruby-dev-builder/ext/socket/tcpsocket.c:76:12 #5 0x7fcadf83ba70 in vm_call0_cfunc_with_frame /home/runner/work/ruby-dev-builder/ruby-dev-builder/./vm_eval.c:164:15 ... ``` A `struct fast_fallback_getaddrinfo_shared` is shared between the main thread and two child threads. This struct contains an array of `fast_fallback_getaddrinfo_entry`. `fast_fallback_getaddrinfo_entry` and `fast_fallback_getaddrinfo_shared` were freed separately, and if `fast_fallback_getaddrinfo_shared` was freed first and then an attempt was made to free a `fast_fallback_getaddrinfo_entry`, a `heap-use-after-free` could occur. This change avoids that possibility by separating the deallocation of the addrinfo memory held by `fast_fallback_getaddrinfo_entry` from the access and lifecycle of the `fast_fallback_getaddrinfo_entry` itself. Notes: Merged-By: shioimm <shioi.mm@gmail.com>
2025-04-27Use a `set_table` for `rb_vm_struct.unused_block_warning_table`Jean Boussier
Now that we have a hash-set implementation we can use that instead of a hash-table with a static value.
2025-04-13Fix typos `finised` -> `finished` (#13104)Haruna Tsujita
Notes: Merged-By: ioquatix <samuel@codeotaku.com>
2025-04-02Improve backtrace of errors raised by `Socket.tcp_with_fast_fallback`Jean Boussier
[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`. Notes: Merged: https://github.com/ruby/ruby/pull/13041
2025-03-15Fix crash in TCPSocket.openLuke Jahnke
Fix segfault crash observable with TCPSocket.open(nil, nil) Notes: Merged: https://github.com/ruby/ruby/pull/12934
2025-03-10Fix `Socket.tcp_with_fast_fallback` to be usable from a RactorJean Boussier
[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' ``` Notes: Merged: https://github.com/ruby/ruby/pull/12896
2025-02-22Add description for Socket::Ifaddr#flags.Tanaka Akira
2025-02-18Tweak: Add prefix to non-static function names (#12764)Misaki Shioi
to avoid conflicts with other functions. This was pointed out in https://github.com/ruby/ruby/pull/11653#discussion_r1837356617 , but it was not fixed at that time. Notes: Merged-By: shioimm <shioi.mm@gmail.com>
2025-02-03Do not save ResolutionError if resolution succeeds for any address family ↵Misaki Shioi
(#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 Notes: Merged-By: shioimm <shioi.mm@gmail.com>
2025-01-29Ensure that memory is not freed before calling ↵Misaki Shioi
`free_fast_fallback_getaddrinfo_*` (#12661) Ensure that `getaddrinfo_entry` and `getaddrinfo_shared` exist before free them in the main thread. Notes: Merged-By: shioimm <shioi.mm@gmail.com>
2025-01-06Fix typo for private constant in SocketRaul Gutierrez Segales
Signed-off-by: Raul Gutierrez Segales <rgs@itevenworks.net> Notes: Merged: https://github.com/ruby/ruby/pull/12506
2024-12-25Introduce a timeout to prevent `rb_thread_fd_select` from hanging with ↵Misaki Shioi
write(2) failure (#12457) Rarely, there are cases where a write(2) call from a child thread to notify the main thread of the completion of name resolution fails. If this happens while the main thread is waiting in `rb_thread_fd_select`, rb_thread_fd_select may not notice that the name resolution has completed and end up hanging. This issue becomes a problem when there are no sockets currently being connected, no addresses ready for immediate connection attempts, and name resolution has already completed for one address family while the main thread is waiting for the name resolution of the other address family. (If name resolution is not completed for either address family, the chances of write(2) failing in both child threads are likely low.) To avoid this issue, a timeout is introduced to rb_thread_fd_select under the above conditions. This way, even if the issue occurs, the completion of name resolution should still be detected in the subsequent `if (!resolution_store.is_all_finished) ...` block. Notes: Merged-By: shioimm <shioi.mm@gmail.com>
2024-12-23Improve doc for `Socket::ResolutionError` (#12434)Misaki Shioi
Also, a topic about Socket::ResolutionError is added to NEWS Notes: Merged-By: shioimm <shioi.mm@gmail.com>