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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ lcov*.info
/*-fake.rb
/*.dll
/*.exe
/*.ilk
/*.res
/*.pc
/*.rc
Expand Down
3 changes: 2 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ releases.
* pstore 0.2.1
* 0.2.0 to [v0.2.1][pstore-v0.2.1]
* rdoc 8.0.0
* 7.0.3 to [v7.0.4][rdoc-v7.0.4], [v7.1.0][rdoc-v7.1.0], [v7.2.0][rdoc-v7.2.0]
* 7.0.3 to [v7.0.4][rdoc-v7.0.4], [v7.1.0][rdoc-v7.1.0], [v7.2.0][rdoc-v7.2.0], [v8.0.0][rdoc-v8.0.0]
* win32ole 1.9.3
* 1.9.2 to [v1.9.3][win32ole-v1.9.3]
* irb 1.18.0
Expand Down Expand Up @@ -286,6 +286,7 @@ A lot of work has gone into making Ractors more stable, performant, and usable.
[rdoc-v7.0.4]: https://github.com/ruby/rdoc/releases/tag/v7.0.4
[rdoc-v7.1.0]: https://github.com/ruby/rdoc/releases/tag/v7.1.0
[rdoc-v7.2.0]: https://github.com/ruby/rdoc/releases/tag/v7.2.0
[rdoc-v8.0.0]: https://github.com/ruby/rdoc/releases/tag/v8.0.0
[win32ole-v1.9.3]: https://github.com/ruby/win32ole/releases/tag/v1.9.3
[irb-v1.17.0]: https://github.com/ruby/irb/releases/tag/v1.17.0
[irb-v1.18.0]: https://github.com/ruby/irb/releases/tag/v1.18.0
13 changes: 9 additions & 4 deletions ext/json/parser/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -2625,11 +2625,16 @@ static VALUE cResumableParser_partial_value_body(VALUE self)
missing_object_value = 1;
}

// Copy the value stack as we need to mutate it.
// Copy the value stack as we need to mutate it. The collapse loop folds each
// open container by popping its entries and pushing the single result, so a
// parent always reclaims its child's slot; head exceeds its live size by at
// most one, either for the missing-value placeholder pushed below or for the
// result of folding an empty innermost container. That one spare slot keeps
// rvalue_stack_push from growing (reallocating) this ALLOCV buffer.
long capa = parser.value_stack.head;
parser.value_stack.capa = (capa + missing_object_value);
VALUE tmpbuf, *value_stack_buffer = ALLOCV_N(VALUE, tmpbuf, capa + missing_object_value);
MEMCPY(value_stack_buffer, parser.value_stack.ptr, VALUE, parser.value_stack.capa);
parser.value_stack.capa = capa + 1;
VALUE tmpbuf, *value_stack_buffer = ALLOCV_N(VALUE, tmpbuf, parser.value_stack.capa);
MEMCPY(value_stack_buffer, parser.value_stack.ptr, VALUE, capa);
parser.value_stack.ptr = value_stack_buffer;

JSON_ParserState *state = &parser.state;
Expand Down
3 changes: 1 addition & 2 deletions gc/mmtk/mmtk.c
Original file line number Diff line number Diff line change
Expand Up @@ -965,8 +965,7 @@ size_t
rb_gc_impl_heap_id_for_size(void *objspace_ptr, size_t size)
{
for (int i = 0; i < MMTK_HEAP_COUNT; i++) {
if (size == heap_sizes[i]) return i;
if (size < heap_sizes[i]) return i;
if (size <= heap_sizes[i]) return i;
}

rb_bug("size too big");
Expand Down
6 changes: 2 additions & 4 deletions spec/bundler/bundler/mirror_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -298,15 +298,13 @@

context "with a listening TCP Server" do
def with_server_and_mirror
server = TCPServer.new("0.0.0.0", 0)
mirror = Bundler::Settings::Mirror.new("http://0.0.0.0:#{server.addr[1]}", 1)
server = TCPServer.new("127.0.0.1", 0)
mirror = Bundler::Settings::Mirror.new("http://127.0.0.1:#{server.addr[1]}", 1)
yield server, mirror
server.close unless server.closed?
end

it "probes the server correctly" do
skip "obscure error" if Gem.win_platform?

with_server_and_mirror do |server, mirror|
expect(server.closed?).to be_falsey
expect(probe.replies?(mirror)).to be_truthy
Expand Down
2 changes: 0 additions & 2 deletions spec/bundler/install/git_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@
end

it "displays the ref of the gem repository when using branch~num as a ref" do
skip "maybe branch~num notation doesn't work on Windows' git" if Gem.win_platform?

build_git "foo", "1.0", path: lib_path("foo")
rev = revision_for(lib_path("foo"))[0..6]
update_git "foo", "2.0", path: lib_path("foo"), gemspec: true
Expand Down
11 changes: 11 additions & 0 deletions test/json/resumable_parser_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,17 @@ def test_partial_value
assert_partial_value([1, { "a" => 1, "b" => { "c" => nil } }], '[1, { "a": 1, "b": { "c"')
end

def test_partial_value_collapses_nested_incomplete_containers
# partial_value rebuilds the open containers on a scratch value stack; folding
# an empty inner container pushes a value, so that stack must hold more than its
# live size or the push reallocates the scratch buffer.
assert_partial_value({ "abc" => {} }, '{"abc":{"d')
assert_partial_value({ "a" => { "b" => { "c" => {} } } }, '{"a":{"b":{"c":{"e')
assert_partial_value([1, { "a" => {} }], '[1,{"a":{"d')
assert_partial_value({ "a" => [1, { "b" => [2, { "c" => nil }] }] }, '{"a":[1,{"b":[2,{"c"')
assert_partial_value([1, [2, [3, { "x" => nil }]]], '[1,[2,[3,{"x":[')
end

def test_partial_value_issue_1005
data = <<~JSON
[
Expand Down
64 changes: 38 additions & 26 deletions test/ruby/test_settracefunc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ def target_thread?
Thread.current == @target_thread
end

# Reject trace events from other code interrupting this thread, such as
# finalizers of objects left by other tests (e.g. Tempfile's), whose
# frames are pushed on top of the interrupted frame of this file. An
# event is ours iff the innermost frame, ignoring core methods written
# in Ruby (<internal:*> such as Kernel#tap), belongs to this file.
#
# +locations+ must be the caller_locations captured directly in the
# trace handler; capturing it here would add this method's own frame.
def event_from_this_file?(locations)
innermost = locations.drop_while{|loc| loc.path.start_with?("<internal:")}.first
innermost&.path == __FILE__
end

def test_c_call
events = []
name = "#{self.class}\##{__method__}"
Expand Down Expand Up @@ -1577,6 +1590,7 @@ def test_define_method_on_return
obj = C11492.new
TracePoint.new(:call, :return){|tp|
next unless target_thread?
next unless event_from_this_file?(caller_locations)
events << [tp.event, tp.method_id]
}.enable{
obj.foo_return
Expand All @@ -1588,6 +1602,7 @@ def test_define_method_on_return
obj = C11492.new
TracePoint.new(:call, :return){|tp|
next unless target_thread?
next unless event_from_this_file?(caller_locations)
events << [tp.event, tp.method_id]
}.enable{
obj.foo_break
Expand All @@ -1600,6 +1615,7 @@ def test_define_method_on_return
begin
set_trace_func(lambda{|event, file, lineno, mid, binding, klass|
next unless target_thread?
next unless event_from_this_file?(caller_locations)
case event
when 'call', 'return'
events << [event, mid]
Expand All @@ -1617,6 +1633,7 @@ def test_define_method_on_return
begin
set_trace_func(lambda{|event, file, lineno, mid, binding, klass|
next unless target_thread?
next unless event_from_this_file?(caller_locations)
case event
when 'call', 'return'
events << [event, mid]
Expand Down Expand Up @@ -1904,14 +1921,7 @@ def test_tracepoint_callee_id
events = []
capture_events = Proc.new{|tp|
next unless target_thread?
# Skip events from other code interrupting this thread, such as
# finalizers of objects left by other tests (e.g. Tempfile's),
# whose frames are pushed on top of the interrupted frame of this
# file. The event is ours iff the innermost frame, ignoring core
# methods written in Ruby (e.g. Kernel#tap in <internal:kernel>),
# belongs to this file.
innermost = caller_locations.drop_while{|loc| loc.path.start_with?("<internal:")}.first
next unless innermost&.path == __FILE__
next unless event_from_this_file?(caller_locations)
events << [tp.event, tp.method_id, tp.callee_id]
}

Expand Down Expand Up @@ -2968,6 +2978,10 @@ def test_tracepoint_thread_end_with_exception
assert_kind_of(Thread, target_thread)
end

private def finalized(done)
proc {done[0] = true}
end

def test_tracepoint_garbage_collected_when_disable
before_count_stat = 0
before_count_objspace = 0
Expand All @@ -2982,18 +2996,17 @@ def test_tracepoint_garbage_collected_when_disable
tp.enable
Class.inspect # c_call, c_return invoked
tp.disable
tp_id = tp.object_id
done = [false]
ObjectSpace.define_finalizer(tp, finalized(done))
tp = nil

gc_times = 0
gc_max_retries = 10
EnvUtil.suppress_warning do
until (ObjectSpace._id2ref(tp_id) rescue nil).nil?
GC.start
gc_times += 1
if gc_times == gc_max_retries
break
end
until done[0]
GC.start
gc_times += 1
if gc_times == gc_max_retries
break
end
end
return if gc_times == gc_max_retries
Expand All @@ -3002,12 +3015,12 @@ def test_tracepoint_garbage_collected_when_disable
TracePoint.stat.each do |v|
after_count_stat += 1
end
assert after_count_stat <= before_count_stat
assert_operator after_count_stat, :<=, before_count_stat
after_count_objspace = 0
ObjectSpace.each_object(TracePoint) do
after_count_objspace += 1
end
assert after_count_objspace <= before_count_objspace
assert_operator after_count_objspace, :<=, before_count_objspace
end

def test_tp_ractor_local_untargeted
Expand Down Expand Up @@ -3101,7 +3114,9 @@ def foo
def test_tracepoints_not_disabled_by_ractor_gc
assert_ractor("#{<<~"begin;"}\n#{<<~'end;'}")
begin;
$-w = nil # uses ObjectSpace._id2ref
def finalized(done)
proc {done[0] = true}
end
def hi = "hi"
greetings = 0
tp_target = TracePoint.new(:call) do |tp|
Expand All @@ -3117,12 +3132,13 @@ def hi = "hi"

r = Ractor.new { 10 }
r.join
ractor_id = r.object_id
done = [false]
ObjectSpace.define_finalizer(r, finalized(done))
r = nil # allow gc for ractor
gc_max_retries = 15
gc_times = 0
# force GC of ractor (or try, because we have a conservative GC)
until (ObjectSpace._id2ref(ractor_id) rescue nil).nil?
until done[0]
GC.start
gc_times += 1
if gc_times == gc_max_retries
Expand All @@ -3140,11 +3156,7 @@ def hi = "hi"
tp_target.disable
tp_global.disable
assert_equal 5, greetings
if gc_times == gc_max_retries # _id2ref never raised
assert_equal 6, raises
else
assert_equal 7, raises
end
assert_equal 6, raises
end;
end

Expand Down
7 changes: 3 additions & 4 deletions test/rubygems/test_gem_compact_index_client_cache_file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,12 @@ def test_commit_after_close_raises
end

def test_write_preserves_permissions
pend "chmod is unreliable on Windows" if Gem.win_platform?

@path.binwrite "old"
@path.chmod 0o600
@path.chmod 0o400

CacheFile.write(@path, "new")

assert_equal 0o600, @path.stat.mode & 0o777
assert_equal "new", @path.binread
assert_equal 0, @path.stat.mode & 0o200, "expected CacheFile.write to preserve the original read-only permission"
end
end
4 changes: 2 additions & 2 deletions test/rubygems/test_gem_specification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3159,14 +3159,14 @@ def test_validate_require_paths_with_invalid_types
end

def test_validate_files
pend "test_validate_files skipped on MS Windows (symlink)" if Gem.win_platform?
pend "Symlinks not supported or not enabled" unless symlink_supported?
util_setup_validate

@a1.files += ["lib", "lib2"]
@a1.extensions << "ext/a/extconf.rb"

Dir.chdir @tempdir do
FileUtils.ln_s "lib/code.rb", "lib2" unless vc_windows?
FileUtils.ln_s "lib/code.rb", "lib2"

use_ui @ui do
@a1.validate
Expand Down
3 changes: 2 additions & 1 deletion tool/lib/_tmpdir.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,5 @@ def list_tree(parent, indent = "", &block)
end
}

ENV["TMPDIR"] = ENV["SPEC_TEMP_DIR"] = ENV["GEM_TEST_TMPDIR"] = tmpdir
ENV["TMPDIR"] = ENV["GEM_TEST_TMPDIR"] = tmpdir
ENV["SPEC_TEMP_DIR"] = File.join(tmpdir, "spec")