Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
cbcbbb2
Let Ractor::IsolationError report correct constant path
osyoyu Dec 15, 2025
0fe111c
Respect encoding of ID in exception messages
osyoyu Dec 16, 2025
f483484
[DOC] Fix call-seq of Method#box
peterzhu2118 Dec 16, 2025
74a3653
Fix: Recalculate the timeout duration considering `open_timeout` (#15…
shioimm Dec 17, 2025
2117e61
Disabled gem sync for Ruby 4.0 release
hsbt Dec 17, 2025
3b66efd
Bundle RubyGems 4.0.2 and Bundler 4.0.2
hsbt Dec 17, 2025
87274c7
Update default gems list at 3b66efda523fc33070aee6097898db [ci skip]
matzbot Dec 17, 2025
f430fbb
IO::Buffer: Fill the test for `IO::Buffer#clear`
nobu Nov 22, 2025
9519d16
IO::Buffer: Guard arguments from GC
nobu Nov 22, 2025
c353b62
[Bug #21787] IO::Buffer: Check addition overflows
nobu Nov 22, 2025
7c402d2
IO::Buffer: Warn as experimental at allocation
nobu Dec 11, 2025
e354e9b
refactor: utilize a predefined macro
mame Dec 17, 2025
0e2962f
[ruby/io-wait] bump up to 0.4.0
nobu Dec 17, 2025
4c38419
Update default gems list at 0e2962f917db1b20a6d34b6105b376 [ci skip]
matzbot Dec 17, 2025
7b5691c
`Socket.tcp` and `TCPSocket.new` raises `IO::TiemoutError` with user …
shioimm Dec 17, 2025
8850807
[ruby/psych] v5.3.1
hsbt Dec 17, 2025
0162449
[ruby/time] v0.4.2
hsbt Dec 17, 2025
8e25812
[ruby/timeout] v0.6.0
hsbt Dec 17, 2025
d5257be
Bundle stringio-3.2.0
hsbt Dec 17, 2025
df18f3b
Bundle strscan-3.1.6
hsbt Dec 17, 2025
fedafec
[ruby/net-http] v0.9.0
hsbt Dec 17, 2025
b80fc8b
[ruby/net-http] Freeze more constants for Ractor compatibility
rhenium Dec 13, 2025
26447b3
[ruby/net-http] v0.9.1
hsbt Dec 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/sync_default_gems.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
name: Sync default gems

env:
DEFAULT_GEM_SYNC_ENABLED: false

on:
workflow_dispatch:
inputs:
Expand Down Expand Up @@ -58,7 +62,7 @@ jobs:
run: |
git pull --rebase origin ${GITHUB_REF#refs/heads/}
git push origin ${GITHUB_REF#refs/heads/}
if: ${{ steps.sync.outputs.update }}
if: ${{ steps.sync.outputs.update && env.DEFAULT_GEM_SYNC_ENABLED == 'true' }}
env:
EMAIL: svn-admin@ruby-lang.org
GIT_AUTHOR_NAME: git
Expand Down
6 changes: 3 additions & 3 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,8 @@ The following default gem is added.

The following default gems are updated.

* RubyGems 4.0.1
* bundler 4.0.1
* RubyGems 4.0.2
* bundler 4.0.2
* date 3.5.1
* digest 3.2.1
* english 0.8.1
Expand All @@ -276,7 +276,7 @@ The following default gems are updated.
* forwardable 1.4.0
* io-console 0.8.2
* io-nonblock 0.3.2
* io-wait 0.4.0.dev
* io-wait 0.4.0
* ipaddr 1.2.8
* json 2.18.0
* net-http 0.8.0
Expand Down
14 changes: 14 additions & 0 deletions bootstraptest/test_ractor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,20 @@ def str; STR; end
end
RUBY

# The correct constant path shall be reported
assert_equal "can not access non-shareable objects in constant Object::STR by non-main Ractor.", <<~'RUBY', frozen_string_literal: false
STR = "hello"
module M
def self.str; STR; end
end

begin
Ractor.new{ M.str }.join
rescue Ractor::RemoteError => e
e.cause.message
end
RUBY

# Setting non-shareable objects into constants by other Ractors is not allowed
assert_equal 'can not set constants with non-shareable objects by non-main Ractors', <<~'RUBY', frozen_string_literal: false
class C
Expand Down
2 changes: 1 addition & 1 deletion ext/io/wait/io-wait.gemspec
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
_VERSION = "0.4.0.dev"
_VERSION = "0.4.0"

Gem::Specification.new do |spec|
spec.name = "io-wait"
Expand Down
2 changes: 1 addition & 1 deletion ext/psych/lib/psych/versions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module Psych
# The version of Psych you are using
VERSION = '5.3.0'
VERSION = '5.3.1'

if RUBY_ENGINE == 'jruby'
DEFAULT_SNAKEYAML_VERSION = '2.10'.freeze
Expand Down
45 changes: 34 additions & 11 deletions ext/socket/ipsocket.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ struct inetsock_arg
void
rsock_raise_user_specified_timeout(void)
{
VALUE errno_module = rb_const_get(rb_cObject, rb_intern("Errno"));
VALUE etimedout_error = rb_const_get(errno_module, rb_intern("ETIMEDOUT"));
rb_raise(etimedout_error, "user specified timeout");
rb_raise(rb_eIOTimeoutError, "user specified timeout");
}

static VALUE
Expand Down Expand Up @@ -606,6 +604,7 @@ init_fast_fallback_inetsock_internal(VALUE v)
struct timeval user_specified_open_timeout_storage;
struct timeval *user_specified_open_timeout_at = NULL;
struct timespec now = current_clocktime_ts();
VALUE starts_at = current_clocktime();

if (!NIL_P(open_timeout)) {
struct timeval open_timeout_tv = rb_time_interval(open_timeout);
Expand All @@ -619,7 +618,14 @@ init_fast_fallback_inetsock_internal(VALUE v)
arg->getaddrinfo_shared = NULL;

int family = arg->families[0];
unsigned int t = NIL_P(resolv_timeout) ? 0 : rsock_value_timeout_to_msec(resolv_timeout);
unsigned int t;
if (!NIL_P(open_timeout)) {
t = rsock_value_timeout_to_msec(open_timeout);
} else if (!NIL_P(open_timeout)) {
t = rsock_value_timeout_to_msec(resolv_timeout);
} else {
t = 0;
}

arg->remote.res = rsock_addrinfo(
arg->remote.host,
Expand Down Expand Up @@ -833,14 +839,22 @@ init_fast_fallback_inetsock_internal(VALUE v)
status = connect(fd, remote_ai->ai_addr, remote_ai->ai_addrlen);
last_family = remote_ai->ai_family;
} else {
if (!NIL_P(connect_timeout)) {
user_specified_connect_timeout_storage = rb_time_interval(connect_timeout);
user_specified_connect_timeout_at = &user_specified_connect_timeout_storage;
VALUE timeout = Qnil;

if (!NIL_P(open_timeout)) {
VALUE elapsed = rb_funcall(current_clocktime(), '-', 1, starts_at);
timeout = rb_funcall(open_timeout, '-', 1, elapsed);
}
if (NIL_P(timeout)) {
if (!NIL_P(connect_timeout)) {
user_specified_connect_timeout_storage = rb_time_interval(connect_timeout);
user_specified_connect_timeout_at = &user_specified_connect_timeout_storage;
}
timeout =
(user_specified_connect_timeout_at && is_infinity(*user_specified_connect_timeout_at)) ?
Qnil : tv_to_seconds(user_specified_connect_timeout_at);
}

VALUE timeout =
(user_specified_connect_timeout_at && is_infinity(*user_specified_connect_timeout_at)) ?
Qnil : tv_to_seconds(user_specified_connect_timeout_at);
io = arg->io = rsock_init_sock(arg->self, fd);
status = rsock_connect(io, remote_ai->ai_addr, remote_ai->ai_addrlen, 0, timeout);
}
Expand Down Expand Up @@ -1305,13 +1319,22 @@ rsock_init_inetsock(
* Maybe also accept a local address
*/
if (!NIL_P(local_host) || !NIL_P(local_serv)) {
unsigned int t;
if (!NIL_P(open_timeout)) {
t = rsock_value_timeout_to_msec(open_timeout);
} else if (!NIL_P(open_timeout)) {
t = rsock_value_timeout_to_msec(resolv_timeout);
} else {
t = 0;
}

local_res = rsock_addrinfo(
local_host,
local_serv,
AF_UNSPEC,
SOCK_STREAM,
0,
0
t
);

struct addrinfo *tmp_p = local_res->ai;
Expand Down
23 changes: 15 additions & 8 deletions ext/socket/lib/socket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,7 @@ def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: ni
# :stopdoc:
def self.tcp_with_fast_fallback(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil, open_timeout: nil)
if local_host || local_port
local_addrinfos = Addrinfo.getaddrinfo(local_host, local_port, nil, :STREAM, timeout: resolv_timeout)
local_addrinfos = Addrinfo.getaddrinfo(local_host, local_port, nil, :STREAM, timeout: open_timeout || resolv_timeout)
resolving_family_names = local_addrinfos.map { |lai| ADDRESS_FAMILIES.key(lai.afamily) }.uniq
else
local_addrinfos = []
Expand All @@ -698,6 +698,7 @@ def self.tcp_with_fast_fallback(host, port, local_host = nil, local_port = nil,
is_windows_environment ||= (RUBY_PLATFORM =~ /mswin|mingw|cygwin/)

now = current_clock_time
starts_at = now
resolution_delay_expires_at = nil
connection_attempt_delay_expires_at = nil
user_specified_connect_timeout_at = nil
Expand All @@ -707,7 +708,7 @@ def self.tcp_with_fast_fallback(host, port, local_host = nil, local_port = nil,

if resolving_family_names.size == 1
family_name = resolving_family_names.first
addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[:family_name], :STREAM, timeout: resolv_timeout)
addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[:family_name], :STREAM, timeout: open_timeout || resolv_timeout)
resolution_store.add_resolved(family_name, addrinfos)
hostname_resolution_result = nil
hostname_resolution_notifier = nil
Expand All @@ -724,7 +725,6 @@ def self.tcp_with_fast_fallback(host, port, local_host = nil, local_port = nil,
thread
}
)

user_specified_resolv_timeout_at = resolv_timeout ? now + resolv_timeout : Float::INFINITY
end

Expand Down Expand Up @@ -758,9 +758,16 @@ def self.tcp_with_fast_fallback(host, port, local_host = nil, local_port = nil,
socket.bind(local_addrinfo) if local_addrinfo
result = socket.connect_nonblock(addrinfo, exception: false)
else
timeout =
if open_timeout
t = open_timeout - (current_clock_time - starts_at)
t.negative? ? 0 : t
else
connect_timeout
end
result = socket = local_addrinfo ?
addrinfo.connect_from(local_addrinfo, timeout: connect_timeout) :
addrinfo.connect(timeout: connect_timeout)
addrinfo.connect_from(local_addrinfo, timeout:) :
addrinfo.connect(timeout:)
end

if result == :wait_writable
Expand Down Expand Up @@ -898,7 +905,7 @@ def self.tcp_with_fast_fallback(host, port, local_host = nil, local_port = nil,
end
end

raise(Errno::ETIMEDOUT, 'user specified timeout') if expired?(now, user_specified_open_timeout_at)
raise(IO::TimeoutError, 'user specified timeout') if expired?(now, user_specified_open_timeout_at)

if resolution_store.empty_addrinfos?
if connecting_sockets.empty? && resolution_store.resolved_all_families?
Expand All @@ -911,7 +918,7 @@ def self.tcp_with_fast_fallback(host, port, local_host = nil, local_port = nil,

if (expired?(now, user_specified_resolv_timeout_at) || resolution_store.resolved_all_families?) &&
(expired?(now, user_specified_connect_timeout_at) || connecting_sockets.empty?)
raise Errno::ETIMEDOUT, 'user specified timeout'
raise IO::TimeoutError, 'user specified timeout'
end
end
end
Expand All @@ -934,7 +941,7 @@ def self.tcp_without_fast_fallback(host, port, local_host, local_port, connect_t

local_addr_list = nil
if local_host != nil || local_port != nil
local_addr_list = Addrinfo.getaddrinfo(local_host, local_port, nil, :STREAM, nil)
local_addr_list = Addrinfo.getaddrinfo(local_host, local_port, nil, :STREAM, nil, timeout: open_timeout || resolv_timeout)
end

timeout = open_timeout ? open_timeout : resolv_timeout
Expand Down
2 changes: 1 addition & 1 deletion ext/stringio/stringio.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
**********************************************************************/

static const char *const
STRINGIO_VERSION = "3.1.9.dev";
STRINGIO_VERSION = "3.2.0";

#include <stdbool.h>

Expand Down
2 changes: 1 addition & 1 deletion ext/strscan/strscan.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ extern size_t onig_region_memsize(const struct re_registers *regs);

#include <stdbool.h>

#define STRSCAN_VERSION "3.1.6.dev"
#define STRSCAN_VERSION "3.1.6"


#ifdef HAVE_RB_DEPRECATE_CONSTANT
Expand Down
38 changes: 24 additions & 14 deletions io_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,8 @@ io_buffer_extract_offset_length(VALUE self, int argc, VALUE argv[], size_t *offs
VALUE
rb_io_buffer_type_allocate(VALUE self)
{
io_buffer_experimental();

struct rb_io_buffer *buffer = NULL;
VALUE instance = TypedData_Make_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);

Expand Down Expand Up @@ -649,8 +651,6 @@ rb_io_buffer_new(void *base, size_t size, enum rb_io_buffer_flags flags)
VALUE
rb_io_buffer_map(VALUE io, size_t size, rb_off_t offset, enum rb_io_buffer_flags flags)
{
io_buffer_experimental();

VALUE instance = rb_io_buffer_type_allocate(rb_cIOBuffer);

struct rb_io_buffer *buffer = NULL;
Expand Down Expand Up @@ -805,8 +805,6 @@ io_flags_for_size(size_t size)
VALUE
rb_io_buffer_initialize(int argc, VALUE *argv, VALUE self)
{
io_buffer_experimental();

rb_check_arity(argc, 0, 2);

struct rb_io_buffer *buffer = NULL;
Expand Down Expand Up @@ -1526,13 +1524,19 @@ VALUE rb_io_buffer_free_locked(VALUE self)
return self;
}

static bool
size_sum_is_bigger_than(size_t a, size_t b, size_t x)
{
struct rbimpl_size_mul_overflow_tag size = rbimpl_size_add_overflow(a, b);
return size.left || size.right > x;
}

// Validate that access to the buffer is within bounds, assuming you want to
// access length bytes from the specified offset.
static inline void
io_buffer_validate_range(struct rb_io_buffer *buffer, size_t offset, size_t length)
{
// We assume here that offset + length won't overflow:
if (offset + length > buffer->size) {
if (size_sum_is_bigger_than(offset, length, buffer->size)) {
rb_raise(rb_eArgError, "Specified offset+length is bigger than the buffer size!");
}
}
Expand Down Expand Up @@ -1842,9 +1846,9 @@ rb_io_buffer_compare(VALUE self, VALUE other)
}

static void
io_buffer_validate_type(size_t size, size_t offset)
io_buffer_validate_type(size_t size, size_t offset, size_t extend)
{
if (offset > size) {
if (size_sum_is_bigger_than(offset, extend, size)) {
rb_raise(rb_eArgError, "Type extends beyond end of buffer! (offset=%"PRIdSIZE" > size=%"PRIdSIZE")", offset, size);
}
}
Expand Down Expand Up @@ -1944,7 +1948,7 @@ static ID RB_IO_BUFFER_DATA_TYPE_##name; \
static VALUE \
io_buffer_read_##name(const void* base, size_t size, size_t *offset) \
{ \
io_buffer_validate_type(size, *offset + sizeof(type)); \
io_buffer_validate_type(size, *offset, sizeof(type)); \
type value; \
memcpy(&value, (char*)base + *offset, sizeof(type)); \
if (endian != RB_IO_BUFFER_HOST_ENDIAN) value = swap(value); \
Expand All @@ -1955,7 +1959,7 @@ io_buffer_read_##name(const void* base, size_t size, size_t *offset) \
static void \
io_buffer_write_##name(const void* base, size_t size, size_t *offset, VALUE _value) \
{ \
io_buffer_validate_type(size, *offset + sizeof(type)); \
io_buffer_validate_type(size, *offset, sizeof(type)); \
type value = unwrap(_value); \
if (endian != RB_IO_BUFFER_HOST_ENDIAN) value = swap(value); \
memcpy((char*)base + *offset, &value, sizeof(type)); \
Expand Down Expand Up @@ -2483,7 +2487,7 @@ io_buffer_memmove(struct rb_io_buffer *buffer, size_t offset, const void *source

io_buffer_validate_range(buffer, offset, length);

if (source_offset + length > source_size) {
if (size_sum_is_bigger_than(source_offset, length, source_size)) {
rb_raise(rb_eArgError, "The computed source range exceeds the size of the source buffer!");
}

Expand Down Expand Up @@ -2569,7 +2573,9 @@ rb_io_buffer_initialize_copy(VALUE self, VALUE source)

io_buffer_initialize(self, buffer, NULL, source_size, io_flags_for_size(source_size), Qnil);

return io_buffer_copy_from(buffer, source_base, source_size, 0, NULL);
VALUE result = io_buffer_copy_from(buffer, source_base, source_size, 0, NULL);
RB_GC_GUARD(source);
return result;
}

/*
Expand Down Expand Up @@ -2654,7 +2660,9 @@ io_buffer_copy(int argc, VALUE *argv, VALUE self)

rb_io_buffer_get_bytes_for_reading(source, &source_base, &source_size);

return io_buffer_copy_from(buffer, source_base, source_size, argc-1, argv+1);
VALUE result = io_buffer_copy_from(buffer, source_base, source_size, argc-1, argv+1);
RB_GC_GUARD(source);
return result;
}

/*
Expand Down Expand Up @@ -2732,7 +2740,9 @@ io_buffer_set_string(int argc, VALUE *argv, VALUE self)
const void *source_base = RSTRING_PTR(string);
size_t source_size = RSTRING_LEN(string);

return io_buffer_copy_from(buffer, source_base, source_size, argc-1, argv+1);
VALUE result = io_buffer_copy_from(buffer, source_base, source_size, argc-1, argv+1);
RB_GC_GUARD(string);
return result;
}

void
Expand Down
Loading