Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 15 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,20 @@ Ruby 4.0 bundled RubyGems and Bundler version 4. see the following links for det
process starts, from the `USER` or `USERNAME` environment variable or
`GetUserName()`. It used to follow later changes to `ENV['USER']`.

* Socket

* On Windows, a connection that is refused or unreachable now raises the
matching `Errno` class as soon as Winsock reports it, instead of
`Errno::ETIMEDOUT` once the whole `connect_timeout` has passed. Code
rescuing `Errno::ETIMEDOUT` there has to rescue the real error instead.

* On Windows, `BasicSocket#getsockopt(:SOCKET, :ERROR)` now reports an
errno as it does on the other platforms, instead of the raw WinSock
error code. Code comparing it with a `WSAE*` value has to compare it
with the matching `Errno::*::Errno` instead.

[[Bug #18661]]

## C API updates

### Embedded TypedData
Expand Down Expand Up @@ -421,6 +435,7 @@ A lot of work has gone into making Ractors more stable, performant, and usable.

## JIT

[Bug #18661]: https://bugs.ruby-lang.org/issues/18661
[Bug #18947]: https://bugs.ruby-lang.org/issues/18947
[Feature #8948]: https://bugs.ruby-lang.org/issues/8948
[Feature #9779]: https://bugs.ruby-lang.org/issues/9779
Expand Down
3 changes: 1 addition & 2 deletions array.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "internal/object.h"
#include "internal/proc.h"
#include "internal/rational.h"
#include "internal/set.h"
#include "internal/string.h"
#include "internal/vm.h"
#include "probes.h"
Expand Down Expand Up @@ -6751,8 +6752,6 @@ rb_ary_count(int argc, VALUE *argv, VALUE ary)
return LONG2NUM(n);
}

VALUE rb_ident_set_new(void);

static VALUE
flatten(VALUE ary, int level)
{
Expand Down
11 changes: 10 additions & 1 deletion cont.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "eval_intern.h"
#include "internal.h"
#include "internal/cont.h"
#include "internal/jit.h"
#include "internal/thread.h"
#include "internal/error.h"
#include "internal/eval.h"
Expand All @@ -29,6 +30,7 @@
#include "internal/sanitizers.h"
#include "internal/vm_map.h"
#include "internal/warnings.h"
#include "iseq.h"
#include "ruby/fiber/scheduler.h"
#include "yjit.h"
#include "vm_core.h"
Expand Down Expand Up @@ -299,8 +301,15 @@ static ID fiber_initialize_keywords[3] = {0};
*/
#if defined(MAP_STACK) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
#define FIBER_STACK_FLAGS (MAP_PRIVATE | MAP_ANON | MAP_STACK)
#define FIBER_PROT_FLAGS (PROT_READ | PROT_WRITE)
#else
#define FIBER_STACK_FLAGS (MAP_PRIVATE | MAP_ANON)
#ifdef PROT_MAX
#define FIBER_BASE_PROT_FLAGS PROT_READ | PROT_WRITE
#define FIBER_PROT_FLAGS (FIBER_BASE_PROT_FLAGS | PROT_MAX(FIBER_BASE_PROT_FLAGS))
#else
#define FIBER_PROT_FLAGS (PROT_READ | PROT_WRITE)
#endif
#endif

#define ERRNOMSG strerror(errno)
Expand Down Expand Up @@ -487,7 +496,7 @@ fiber_pool_allocate_memory(size_t * count, size_t stride)
#else
errno = 0;
size_t mmap_size = (*count)*stride;
void * base = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, FIBER_STACK_FLAGS, -1, 0);
void * base = mmap(NULL, mmap_size, FIBER_PROT_FLAGS, FIBER_STACK_FLAGS, -1, 0);

if (base == MAP_FAILED) {
// If the allocation fails, count = count / 2, and try again.
Expand Down
2 changes: 1 addition & 1 deletion eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#include "eval_intern.h"
#include "internal.h"
#include "internal/class.h"
#include "internal/cont.h"
#include "internal/jit.h"
#include "internal/error.h"
#include "internal/eval.h"
#include "internal/gc.h"
Expand Down
12 changes: 11 additions & 1 deletion ext/socket/lib/socket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@
require 'socket.so'

class Addrinfo
# :stopdoc:
# Windows signals a failed connect(2) through the exceptfds of select(2)
# only. Elsewhere the priority event would just take the wait off the M:N
# thread scheduler, which refuses any event but readable and writable.
# [Bug #18661]
CONNECT_EVENTS = IO::WRITABLE |
(/mswin|mingw|cygwin/.match?(RUBY_PLATFORM) ? IO::PRIORITY : 0)
private_constant :CONNECT_EVENTS
# :startdoc:

# creates an Addrinfo object from the arguments.
#
# The arguments are interpreted as similar to self.
Expand Down Expand Up @@ -56,7 +66,7 @@ def connect_internal(local_addrinfo, timeout=nil) # :yields: socket
when 0 # success or EISCONN, other errors raise
break
when :wait_writable
sock.wait_writable(timeout) or
sock.wait(CONNECT_EVENTS, timeout) or
raise Errno::ETIMEDOUT, "user specified timeout for #{self.ip_address}:#{self.ip_port}"
# Check SO_ERROR instead of relying on the connect_nonblock retry;
# some kernels (e.g. Darwin 27) answer the retry connect(2) with
Expand Down
4 changes: 0 additions & 4 deletions internal/cont.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
* @brief Internal header for Fiber.
*/
#include "ruby/ruby.h" /* for VALUE */
#include "iseq.h"

struct rb_thread_struct; /* in vm_core.h */
struct rb_fiber_struct; /* in cont.c */
Expand All @@ -18,9 +17,6 @@ struct rb_execution_context_struct; /* in vm_core.c */
/* cont.c */
void rb_fiber_reset_root_local_storage(struct rb_thread_struct *);
void ruby_register_rollback_func_for_ensure(VALUE (*ensure_func)(VALUE), VALUE (*rollback_func)(VALUE));
void rb_jit_cont_init(void);
void rb_jit_cont_each_iseq(rb_iseq_callback callback, void *data);
void rb_jit_cont_finish(void);

/* vm.c */
void rb_free_shared_fiber_pool(void);
Expand Down
16 changes: 16 additions & 0 deletions internal/jit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef INTERNAL_JIT_H /*-*-C-*-vi:se ft=c:*/
#define INTERNAL_JIT_H

#include "iseq.h"

typedef void (*rb_iseq_callback)(const rb_iseq_t *, void *);

/* cont.c */
void rb_jit_cont_init(void);
void rb_jit_cont_each_iseq(rb_iseq_callback callback, void *data);
void rb_jit_cont_finish(void);

/* jit.c */
void rb_jit_for_each_iseq(rb_iseq_callback callback, void *data);

#endif /* INTERNAL_JIT_H */
16 changes: 16 additions & 0 deletions internal/set.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef INTERNAL_SET_H /*-*-C-*-vi:se ft=c:*/
#define INTERNAL_SET_H
/**
* @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
* @brief Internal header for Set.
*/
#include "ruby/internal/config.h"
#include "ruby/ruby.h"

VALUE rb_ident_set_new(void);

#endif /* INTERNAL_SET_H */
1 change: 0 additions & 1 deletion iseq.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ iseq_lvar_state_set(uint8_t *buf, unsigned int i, enum lvar_state state)
typedef struct rb_iseq_struct rb_iseq_t;
#define rb_iseq_t rb_iseq_t
#endif
typedef void (*rb_iseq_callback)(const rb_iseq_t *, void *);

extern const ID rb_iseq_shared_exc_local_tbl[];

Expand Down
1 change: 1 addition & 0 deletions jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "iseq.h"
#include "internal/compile.h"
#include "internal/gc.h"
#include "internal/jit.h"
#include "vm_sync.h"
#include "internal/fixnum.h"
#include "internal/hash.h"
Expand Down
12 changes: 9 additions & 3 deletions parse.y
Original file line number Diff line number Diff line change
Expand Up @@ -14826,19 +14826,25 @@ new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_c
if (lhs) {
ID vid = get_nd_vid(p, lhs);
YYLTYPE lhs_loc = lhs->nd_loc;
/* A constant read can raise NameError. Prism has no separate read node
* for `Const op= value` and reports the whole expression, so give the
* NODE_CONST the location of the whole operator assignment as well,
* for consistent Thread::Backtrace::Location#source_range between both
* parsers. */
const YYLTYPE *read_loc = nd_type_p(lhs, NODE_CDECL) ? loc : &lhs_loc;
if (op == tOROP) {
set_nd_value(p, lhs, rhs);
nd_set_loc(lhs, loc);
asgn = NEW_OP_ASGN_OR(gettable(p, vid, &lhs_loc), lhs, loc);
asgn = NEW_OP_ASGN_OR(gettable(p, vid, read_loc), lhs, loc);
}
else if (op == tANDOP) {
set_nd_value(p, lhs, rhs);
nd_set_loc(lhs, loc);
asgn = NEW_OP_ASGN_AND(gettable(p, vid, &lhs_loc), lhs, loc);
asgn = NEW_OP_ASGN_AND(gettable(p, vid, read_loc), lhs, loc);
}
else {
asgn = lhs;
rhs = NEW_CALL(gettable(p, vid, &lhs_loc), op, NEW_LIST(rhs, &rhs->nd_loc), loc);
rhs = NEW_CALL(gettable(p, vid, read_loc), op, NEW_LIST(rhs, &rhs->nd_loc), loc);
set_nd_value(p, asgn, rhs);
nd_set_loc(asgn, loc);
}
Expand Down
2 changes: 1 addition & 1 deletion ruby.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
#include "eval_intern.h"
#include "internal.h"
#include "internal/cmdlineopt.h"
#include "internal/cont.h"
#include "internal/coverage.h"
#include "internal/error.h"
#include "internal/file.h"
Expand All @@ -57,6 +56,7 @@
#include "internal/thread.h"
#include "internal/ruby_parser.h"
#include "internal/variable.h"
#include "prism_compile.h"
#include "ruby/encoding.h"
#include "ruby/thread.h"
#include "ruby/util.h"
Expand Down
85 changes: 72 additions & 13 deletions scheduler.c
Original file line number Diff line number Diff line change
Expand Up @@ -936,52 +936,111 @@ rb_fiber_scheduler_io_pwrite(VALUE scheduler, VALUE io, rb_off_t from, VALUE buf
return rb_thread_io_blocking_operation(io, fiber_scheduler_io_pwrite, (VALUE)&arguments);
}

struct fiber_scheduler_io_memory_arguments {
VALUE scheduler;
VALUE io;
VALUE buffer;
rb_off_t from;
size_t offset;
size_t length;
};

static VALUE
fiber_scheduler_io_read_memory(VALUE _arguments)
{
struct fiber_scheduler_io_memory_arguments *arguments = (void *)_arguments;

return rb_fiber_scheduler_io_read(arguments->scheduler, arguments->io, arguments->buffer, arguments->offset, arguments->length);
}

VALUE
rb_fiber_scheduler_io_read_memory(VALUE scheduler, VALUE io, void *base, size_t size)
{
VALUE buffer = rb_io_buffer_new_locked(base, size, 0);

VALUE result = rb_fiber_scheduler_io_read(scheduler, io, buffer, 0, size);
struct fiber_scheduler_io_memory_arguments arguments = {
.scheduler = scheduler,
.io = io,
.buffer = buffer,
.offset = 0,
.length = size,
};

rb_io_buffer_free_locked(buffer);
return rb_ensure(fiber_scheduler_io_read_memory, (VALUE)&arguments, rb_io_buffer_free_locked, buffer);
}

return result;
static VALUE
fiber_scheduler_io_write_memory(VALUE _arguments)
{
struct fiber_scheduler_io_memory_arguments *arguments = (void *)_arguments;

return rb_fiber_scheduler_io_write(arguments->scheduler, arguments->io, arguments->buffer, arguments->offset, arguments->length);
}

VALUE
rb_fiber_scheduler_io_write_memory(VALUE scheduler, VALUE io, const void *base, size_t size)
{
VALUE buffer = rb_io_buffer_new_locked((void*)base, size, RB_IO_BUFFER_READONLY);

VALUE result = rb_fiber_scheduler_io_write(scheduler, io, buffer, 0, size);
struct fiber_scheduler_io_memory_arguments arguments = {
.scheduler = scheduler,
.io = io,
.buffer = buffer,
.offset = 0,
.length = size,
};

return rb_ensure(fiber_scheduler_io_write_memory, (VALUE)&arguments, rb_io_buffer_free_locked, buffer);
}

rb_io_buffer_free_locked(buffer);
static VALUE
fiber_scheduler_io_pread_memory(VALUE _arguments)
{
struct fiber_scheduler_io_memory_arguments *arguments = (void *)_arguments;

return result;
return rb_fiber_scheduler_io_pread(arguments->scheduler, arguments->io, arguments->from, arguments->buffer, arguments->offset, arguments->length);
}

VALUE
rb_fiber_scheduler_io_pread_memory(VALUE scheduler, VALUE io, rb_off_t from, void *base, size_t size)
{
VALUE buffer = rb_io_buffer_new_locked(base, size, 0);

VALUE result = rb_fiber_scheduler_io_pread(scheduler, io, from, buffer, 0, size);
struct fiber_scheduler_io_memory_arguments arguments = {
.scheduler = scheduler,
.io = io,
.buffer = buffer,
.from = from,
.offset = 0,
.length = size,
};

return rb_ensure(fiber_scheduler_io_pread_memory, (VALUE)&arguments, rb_io_buffer_free_locked, buffer);
}

rb_io_buffer_free_locked(buffer);
static VALUE
fiber_scheduler_io_pwrite_memory(VALUE _arguments)
{
struct fiber_scheduler_io_memory_arguments *arguments = (void *)_arguments;

return result;
return rb_fiber_scheduler_io_pwrite(arguments->scheduler, arguments->io, arguments->from, arguments->buffer, arguments->offset, arguments->length);
}

VALUE
rb_fiber_scheduler_io_pwrite_memory(VALUE scheduler, VALUE io, rb_off_t from, const void *base, size_t size)
{
VALUE buffer = rb_io_buffer_new_locked((void*)base, size, RB_IO_BUFFER_READONLY);

VALUE result = rb_fiber_scheduler_io_pwrite(scheduler, io, from, buffer, 0, size);

rb_io_buffer_free_locked(buffer);
struct fiber_scheduler_io_memory_arguments arguments = {
.scheduler = scheduler,
.io = io,
.buffer = buffer,
.from = from,
.offset = 0,
.length = size,
};

return result;
return rb_ensure(fiber_scheduler_io_pwrite_memory, (VALUE)&arguments, rb_io_buffer_free_locked, buffer);
}

/*
Expand Down
1 change: 1 addition & 0 deletions set.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "internal/object.h"
#include "internal/proc.h"
#include "internal/sanitizers.h"
#include "internal/set.h"
#include "internal/set_table.h"
#include "internal/symbol.h"
#include "internal/variable.h"
Expand Down
3 changes: 2 additions & 1 deletion spec/ruby/core/method/syntax_tree_spec.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
require_relative '../../spec_helper'
require_relative '../../fixtures/source_range_helpers'
require_relative 'shared/syntax_tree'

ruby_version_is "4.1" do
describe "Method#syntax_tree" do
before :each do
@object = -> method { method }

skip "parse.y" if method(:it).syntax_tree.is_a?(RubyVM::AbstractSyntaxTree::Node)
skip "parse.y" unless syntax_tree_returns_prism_node
end

it_behaves_like :method_syntax_tree, :syntax_tree
Expand Down
3 changes: 2 additions & 1 deletion spec/ruby/core/proc/syntax_tree_spec.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
require_relative '../../spec_helper'
require_relative '../../fixtures/source_range_helpers'

ruby_version_is "4.1" do
describe "Proc#syntax_tree" do
before :each do
skip "parse.y" if proc {}.syntax_tree.is_a?(RubyVM::AbstractSyntaxTree::Node)
skip "parse.y" unless syntax_tree_returns_prism_node
end

def return_block(&b)
Expand Down
Loading