<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ruby.git/ext/socket, branch v3_4_9</title>
<subtitle>The Ruby Programming Language</subtitle>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/'/>
<entry>
<title>merge revision(s) beb85e7eeee4163cd45b69645a60cdb942f72c05: [Backport #21705]</title>
<updated>2025-12-08T22:46:06+00:00</updated>
<author>
<name>Takashi Kokubun</name>
<email>takashikkbn@gmail.com</email>
</author>
<published>2025-12-08T22:46:06+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=955decc1da6cd2441c24d22e8909a3e995973769'/>
<id>955decc1da6cd2441c24d22e8909a3e995973769</id>
<content type='text'>
	[PATCH] [Bug #21705] Fix segfaults on Windows

	It should check the type of the argument and coercion before
	converting the encoding.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
	[PATCH] [Bug #21705] Fix segfaults on Windows

	It should check the type of the argument and coercion before
	converting the encoding.
</pre>
</div>
</content>
</entry>
<entry>
<title>Avoid spawning thread for trivial getnameinfo calls</title>
<updated>2025-11-17T21:28:01+00:00</updated>
<author>
<name>John Hawthorn</name>
<email>john@hawthorn.email</email>
</author>
<published>2025-08-20T02:13:00+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=7482835d0b5c9f55662fb7c6586f456354e2b66e'/>
<id>7482835d0b5c9f55662fb7c6586f456354e2b66e</id>
<content type='text'>
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
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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
</pre>
</div>
</content>
</entry>
<entry>
<title>ext/socket: Set raddrinfo thread as detached before thread start (#15194)</title>
<updated>2025-11-14T19:48:40+00:00</updated>
<author>
<name>Luke Gruber</name>
<email>luke.gruber@shopify.com</email>
</author>
<published>2025-11-14T19:48:40+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=9e4829699b544370dd3a83df3e2c6b9168c34159'/>
<id>9e4829699b544370dd3a83df3e2c6b9168c34159</id>
<content type='text'>
Backport of https://github.com/ruby/ruby/pull/15142

[Bug #21679]</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Backport of https://github.com/ruby/ruby/pull/15142

[Bug #21679]</pre>
</div>
</content>
</entry>
<entry>
<title>merge revision(s) d77e02bd85ab7f841df8d473bac214b9a92a3506: [Backport #21497]</title>
<updated>2025-07-14T21:48:27+00:00</updated>
<author>
<name>Takashi Kokubun</name>
<email>takashikkbn@gmail.com</email>
</author>
<published>2025-07-14T21:48:27+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=782aef10bbdb63aba6d71e4f5f1876888c70efcb'/>
<id>782aef10bbdb63aba6d71e4f5f1876888c70efcb</id>
<content type='text'>
	[Bug #21497] [ruby/socket]: add full prototype
	MIME-Version: 1.0
	Content-Type: text/plain; charset=UTF-8
	Content-Transfer-Encoding: 8bit

	otherwise, gcc 15 will complain:

	&gt; init.c:573:19: error: too many arguments to function ‘Rconnect’; expected 0, have 3
	&gt;   573 |     return (VALUE)Rconnect(arg-&gt;fd, arg-&gt;sockaddr, arg-&gt;len);
	&gt;       |                   ^~~~~~~~ ~~~~~~~
	&gt; In file included from init.c:11:
	&gt; rubysocket.h:294:5: note: declared here
	&gt;   294 | int Rconnect();
	&gt;       |     ^~~~~~~~

	&gt; sockssocket.c:33:9: error: too many arguments to function ‘SOCKSinit’; expected 0, have 1
	&gt;    33 |         SOCKSinit("ruby");
	&gt;       |         ^~~~~~~~~ ~~~~~~
	&gt; In file included from sockssocket.c:11:
	&gt; rubysocket.h:293:6: note: declared here
	&gt;   293 | void SOCKSinit();
	&gt;       |      ^~~~~~~~~

	Signed-off-by: Z. Liu &lt;zhixu.liu@gmail.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
	[Bug #21497] [ruby/socket]: add full prototype
	MIME-Version: 1.0
	Content-Type: text/plain; charset=UTF-8
	Content-Transfer-Encoding: 8bit

	otherwise, gcc 15 will complain:

	&gt; init.c:573:19: error: too many arguments to function ‘Rconnect’; expected 0, have 3
	&gt;   573 |     return (VALUE)Rconnect(arg-&gt;fd, arg-&gt;sockaddr, arg-&gt;len);
	&gt;       |                   ^~~~~~~~ ~~~~~~~
	&gt; In file included from init.c:11:
	&gt; rubysocket.h:294:5: note: declared here
	&gt;   294 | int Rconnect();
	&gt;       |     ^~~~~~~~

	&gt; sockssocket.c:33:9: error: too many arguments to function ‘SOCKSinit’; expected 0, have 1
	&gt;    33 |         SOCKSinit("ruby");
	&gt;       |         ^~~~~~~~~ ~~~~~~
	&gt; In file included from sockssocket.c:11:
	&gt; rubysocket.h:293:6: note: declared here
	&gt;   293 | void SOCKSinit();
	&gt;       |      ^~~~~~~~~

	Signed-off-by: Z. Liu &lt;zhixu.liu@gmail.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Fix `heap-use-after-free` in `free_fast_fallback_getaddrinfo_entry` (#13231)</title>
<updated>2025-06-18T18:09:20+00:00</updated>
<author>
<name>Misaki Shioi</name>
<email>31817032+shioimm@users.noreply.github.com</email>
</author>
<published>2025-05-03T12:39:57+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=c57efbfb3ac3848f954735600bbab1ea814dd742'/>
<id>c57efbfb3ac3848f954735600bbab1ea814dd742</id>
<content type='text'>
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.</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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.</pre>
</div>
</content>
</entry>
<entry>
<title>Ensure that memory is not freed before calling `free_fast_fallback_getaddrinfo_*` (#12661)</title>
<updated>2025-06-18T18:09:20+00:00</updated>
<author>
<name>Misaki Shioi</name>
<email>31817032+shioimm@users.noreply.github.com</email>
</author>
<published>2025-01-29T13:19:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=584365af7baeb80b74d31a26b8ec51e66b2ccc1a'/>
<id>584365af7baeb80b74d31a26b8ec51e66b2ccc1a</id>
<content type='text'>
Ensure that `getaddrinfo_entry` and `getaddrinfo_shared` exist before free them in the main thread.</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Ensure that `getaddrinfo_entry` and `getaddrinfo_shared` exist before free them in the main thread.</pre>
</div>
</content>
</entry>
<entry>
<title>Fix crash in TCPSocket.open</title>
<updated>2025-04-09T23:02:37+00:00</updated>
<author>
<name>Luke Jahnke</name>
<email>luke.jahnke@gmail.com</email>
</author>
<published>2025-03-14T13:38:33+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=7e093fb43a692935823de1bb32ac4f05e46329bb'/>
<id>7e093fb43a692935823de1bb32ac4f05e46329bb</id>
<content type='text'>
Fix segfault crash observable with TCPSocket.open(nil, nil)
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Fix segfault crash observable with TCPSocket.open(nil, nil)
</pre>
</div>
</content>
</entry>
<entry>
<title>Improve backtrace of errors raised by `Socket.tcp_with_fast_fallback`</title>
<updated>2025-04-02T16:16:27+00:00</updated>
<author>
<name>Jean Boussier</name>
<email>jean.boussier@gmail.com</email>
</author>
<published>2025-04-02T10:08:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=e3fc29a9b7fd7869723d2e13185c1387c6d026db'/>
<id>e3fc29a9b7fd7869723d2e13185c1387c6d026db</id>
<content type='text'>
[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`.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
[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`.
</pre>
</div>
</content>
</entry>
<entry>
<title>Fix `Socket.tcp_with_fast_fallback` to be usable from a Ractor</title>
<updated>2025-03-11T16:16:22+00:00</updated>
<author>
<name>Jean Boussier</name>
<email>jean.boussier@gmail.com</email>
</author>
<published>2025-03-10T20:18:59+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=0e416faf450159a989fba87b41f3e3874a4af129'/>
<id>0e416faf450159a989fba87b41f3e3874a4af129</id>
<content type='text'>
[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'
```
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
[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'
```
</pre>
</div>
</content>
</entry>
<entry>
<title>merge revision(s) 1683dadb19876f0a64589bdbbcf6fff8143f78ff: [Backport #21088]</title>
<updated>2025-02-14T05:13:47+00:00</updated>
<author>
<name>Takashi Kokubun</name>
<email>takashikkbn@gmail.com</email>
</author>
<published>2025-02-14T05:13:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=319c3c70385a63aaea3c1a68a79c70cfd533c6b6'/>
<id>319c3c70385a63aaea3c1a68a79c70cfd533c6b6</id>
<content type='text'>
	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
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
	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
</pre>
</div>
</content>
</entry>
</feed>
