10277 Commits
Author SHA1 Message Date
Douglas Eichelberger 27204205e6 Reset the fork lock in the child without unlocking it
A thread that is waiting for the fork lock when another thread forks
exists only in the parent, but on macOS the child's copy of the lock
still counts it. After the child unlocks its copy,
pthread_rwlock_destroy() and pthread_rwlock_init() fail with EBUSY, so
the child aborts with
"[BUG] pthread_rwlock_destroy: Resource busy (EBUSY)". Lookup threads
wait for the lock whenever a fork holds it, so a process that resolves
names in background threads while it forks loses a child now and then.

Reset the child's copy by assigning PTHREAD_RWLOCK_INITIALIZER, as
rb_internal_thread_event_hooks_rw_lock_atfork() does for its lock, and
do not unlock it first. With a waiter counted, macOS's unlock enters the
kernel to wake it, and the state that leaves behind for the lock's
address survives the assignment, so a later waiter in the child can
sleep forever although no thread holds the lock. FreeBSD already skipped
the unlock in the child (dc8c382266), and on glibc the child's unlock
does not release the write lock anyway.

[Bug #22445]
2026-10-15 12:37:17 -07:00
Douglas Eichelberger 59db3a3a81 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]

(cherry picked from commit 44f7c6b00d)
2026-10-14 17:15:16 -07:00
Randy Stauner 4ac2a34ced [Bug #22383] Fix inverted STR_SHARED check in rb_str_tmp_frozen_release
45a2c95d0f mistakenly rewrote

    FL_TEST_RAW(orig, STR_SHARED) && !FL_TEST_RAW(orig, STR_TMPLOCK|RUBY_FL_FREEZE)

as

    FL_TEST_RAW(orig, STR_SHARED | STR_TMPLOCK) == STR_TMPLOCK

requiring orig to not be shared, the opposite of the original
condition.  orig always shares the buffer with tmp here, so the buffer
was never given back and the string stayed shared until its next
modification copied it.  The code then read aux.shared from strings
that are not shared, where the union holds aux.capa.

This should be backported to 4.0
2026-09-25 08:48:32 -07:00
mugitti9 b9a660f6e5 [Bug #22269] Make coverage_enabled: false effective for compile/compile_file (#18533)
Use it in Coverage.line_stub so compiling the stub does not overwrite already-collected coverage data.

Fixes: [Bug #22269]
2026-09-01 09:41:08 -07:00
Hiroshi SHIBATAandClaude Fable 5 791000ba79 [Backport #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-19 10:17:34 -07:00
Randy Stauner 86c23c9e51 Avoid reading TypedData type after dfree
[Bug #22101] (Backport)
2026-06-10 18:01:41 -07:00
Takashi Kokubun c7a7bc986c Merge branch 'ruby_4_0' into v4.0.5 2026-05-19 16:23:48 -07:00
Misaki Shioi 6f1fa82e2e Fix reading freed memory in rb_getaddrinfo 2026-05-19 16:22:08 -07:00
Kazuki Yamaguchi cd38f6c5e1 Merge openssl-4.0.2
The changes can be found at:

    https://github.com/ruby/openssl/compare/v4.0.1...v4.0.2
2026-05-13 15:01:28 -07:00
Kazuki Yamaguchi 729e1512df Merge openssl-4.0.1
The changes can be found at:

    https://github.com/ruby/openssl/compare/v4.0.0...v4.0.1
2026-05-13 15:01:28 -07:00
Takashi Kokubun 8539f0b386 merge revision(s) c0d86a0103de7130943d54b4a290b76ec7e0c135,47e061277ac194a36659510bcf4f3190bde629a6: [Backport #21952]
class.c: rb_class_duplicate_classext also dup content of cvc_tbl

	[Bug #21952]

	Shallow copying the table result in the same memory being shared
	between multiple box, causing double free when one of the box
	is garbage collected.

	---

	class.c: Make cvc_tbl a managed object

	[Bug #21952]

	Solves the double-free or use after-free concern with boxes.
	Now entries can safely be used for copy-on-write.

	Also is likely necessary to make it save to read cvar from
	secondary ractors, as allowed since: ab32c0e690
2026-05-11 13:54:55 -07:00
Hiroshi SHIBATA 636523d0a5 Merge zlib-3.2.3 2026-03-09 08:19:27 -07:00
Yusuke Endoh 2d0d95305c ext/-test-/scheduler/scheduler.c: explicitly ignore the result of write
```
scheduler.c:44:5: warning: ignoring return value of ‘write’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
   44 |     write(blocking_state->notify_descriptor, "x", 1);
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
2025-12-24 21:09:33 +09:00
Peter Zhu 342d25785c [DOC] Fix backticks in Coverage.peek_result 2025-12-23 22:30:54 -05: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
Luke Gruber 56b67f1684 ObjectSpace.{dump,dump_all,dump_shapes} needs vm barrier. (#15569)
This allows these methods to be called from ractors.

Add new exported function `rb_vm_lock_with_barrier()` that requires
users to include "vm_sync.h"
2025-12-17 12:17:30 -05: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
Hiroshi SHIBATA df18f3baa6 Bundle strscan-3.1.6 2025-12-17 15:47:43 +09:00
Hiroshi SHIBATA d5257bea48 Bundle stringio-3.2.0 2025-12-17 15:47:43 +09:00
Hiroshi SHIBATA 8850807eb1 [ruby/psych] v5.3.1
https://github.com/ruby/psych/commit/8345af9ffb
2025-12-17 15:47:43 +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
Nobuyoshi Nakada 0e2962f917 [ruby/io-wait] bump up to 0.4.0
https://github.com/ruby/io-wait/commit/ae676c9d6d
2025-12-17 14:16:38 +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
Nobuyoshi Nakada f4c48505ca Box: move extensions from namespace to box 2025-12-16 16:53:13 +09:00
nick evans b3f0fb5618 [ruby/psych] Replace C extension with Data#initialize bind_call
https://github.com/ruby/psych/commit/6a826693ba
2025-12-15 22:48:40 +00: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
Kazuki Yamaguchi f079373185 [ruby/openssl] Ruby/OpenSSL 4.0.0
https://github.com/ruby/openssl/commit/5af1edab18
2025-12-15 09:50:30 +00:00
Kazuki Yamaguchi f06eb75646 [ruby/openssl] ossl.c: improve docs for constants and methods under ::OpenSSL
https://github.com/ruby/openssl/commit/b0de8ba9bd
2025-12-15 09:09:49 +00:00
Kazuki Yamaguchi ee6ba41bfd [ruby/openssl] Freeze more constants for Ractor compatibility
https://github.com/ruby/openssl/commit/695126f582
2025-12-15 09:09:49 +00:00
Kazuki Yamaguchi 674c3d73e0 [ruby/openssl] pkcs7: raise OpenSSL::PKCS7::PKCS7Error in #initialize
When d2i_PKCS7_bio() and PEM_read_bio_PKCS7() fail to decode the input,
OpenSSL::PKCS7.new currently raises ArgumentError. The usual practice
in ruby/openssl where an error originates from the underlying OpenSSL
library is to raise OpenSSL::OpenSSLError.

Raise OpenSSL::PKCS7::PKCS7Error instead for consistency with
OpenSSL::PKCS7.read_smime and all other existing #initialize methods
that handle DER/PEM-encoded inputs.

https://github.com/ruby/openssl/commit/67a608ce53
2025-12-14 10:46:27 +00:00
Kazuki Yamaguchi 7969b65418 [ruby/openssl] x509cert: update doc for OpenSSL::X509::Certificate#==
Mention the underlying OpenSSL function. Add a note about the unreliable
comparison when called on an incomplete object.

Fixes https://github.com/ruby/openssl/issues/844

https://github.com/ruby/openssl/commit/736af5b3c7
2025-12-14 10:46:13 +00:00
Nobuyoshi Nakada 9e22037eb5 [ruby/io-console] bump up to 0.8.2
https://github.com/ruby/io-console/commit/fbc7e1f31f
2025-12-14 02:59:10 +00:00
Nobuyoshi Nakada bc2a8a002a [Bug #21779] Uniquify InitVM functions as well as Init
Avoid possible name conflict when `--with-static-linked-ext`.
2025-12-14 11:11:27 +09:00
Nobuyoshi Nakada 01db5d71a8 Removed duplicate code 2025-12-14 10:57:42 +09:00
Kazuki Yamaguchi e8d32dddc0 [ruby/openssl] ossl.c: implement OpenSSL::OpenSSLError#detailed_message
An OpenSSL function sometimes puts more than one error entry into the
thread-local OpenSSL error queue. Currently, we use the highest-level
entry for generating the exception message and discard the rest.

Let ossl_make_error() capture all current OpenSSL error queue contents
into OpenSSL::OpenSSLError#errors and extend
OpenSSL::OpenSSLError#detailed_message to include the information.

An example:

    $ ruby -Ilib -ropenssl -e'OpenSSL::X509::ExtensionFactory.new.create_ext("a", "b")'
    -e:1:in 'OpenSSL::X509::ExtensionFactory#create_ext': a = b: error in extension (name=a, value=b) (OpenSSL::X509::ExtensionError)
    OpenSSL error queue reported 2 errors:
    error:11000082:X509 V3 routines:do_ext_nconf:unknown extension name
    error:11000080:X509 V3 routines:X509V3_EXT_nconf_int:error in extension (name=a, value=b)
            from -e:1:in '<main>'

https://github.com/ruby/openssl/commit/d28f7a9a13
2025-12-13 16:57:53 +00:00
Nobuyoshi Nakada 8f2c479fa5 [ruby/io-console] strip trailing spaces [ci skip]
https://github.com/ruby/io-console/commit/379e7c17ed
2025-12-13 21:37:52 +09:00
YO4 3a4ad76f9d [ruby/io-console] console_cursor_pos respects scroll position on windows
https://github.com/ruby/io-console/commit/ae33785820
2025-12-13 21:37:51 +09:00
YO4 c8fd840599 [ruby/io-console] console_goto respects scroll position on windows
https://github.com/ruby/io-console/commit/d2a6c69697
2025-12-13 21:37:51 +09:00
YO4 2912825829 [ruby/io-console] avoid jumping scroll position when winsize changed
On windows, IO.console.winsize= now respects the current view area and screen buffer size.

https://github.com/ruby/io-console/commit/817aa65ea3
2025-12-13 21:37:51 +09:00
Nobuyoshi Nakada 9dbbdcc33f [ruby/io-console] Remove useless rb_check_arity() call
https://github.com/ruby/io-console/commit/df444b93f1
2025-12-13 11:34:11 +00:00
Samuel Williams e2fe0aae43 Avoid race condition in test_without_handle_interrupt_signal_works. (#15504) 2025-12-12 22:12:41 +13:00
Jean Boussier 04299ca184 monitor.c: skip GET_EC() on exit 2025-12-12 00:29:21 +01:00
kares 4ab45e8f0c [ruby/psych] bump snakeyaml-engine to 2.10 (jruby)
https://github.com/ruby/psych/commit/506bf75ab2
2025-12-11 15:01:04 +00:00
Jean Boussier 6b469b7e40 [ruby/json] Release 2.18.0
https://github.com/ruby/json/commit/1cdd2122d5
2025-12-11 10:58:31 +00:00
Jean Boussier 6ad4e6a298 [ruby/json] Add allow_control_characters parsing option
While it's not allowed by the spec, some parsers like Oj do
accept it, and it can be blocking a transition.

Having this feature can help people migrate.

https://github.com/ruby/json/commit/3459499cb3
2025-12-11 10:53:15 +00:00
Jean Boussier ccfd31162a Remove object_id in NEWOBJ tracepoint test
Generating an object_id for any type other than T_OBJECT (and T_CLASS)
will inevitably allocate an IMEMO/fields objects, which isn't supported
in a NEWOBJ tracepoint.

See: https://bugs.ruby-lang.org/issues/21710#note-23
2025-12-10 21:56:40 +01:00
John Hawthorn 41ee65899a Always treat encoding as TYPEDDATA
Encodings are RTypedData, not the deprecated RData. Although the
structures are compatible we should use the correct API.
2025-12-10 09:49:18 -08:00