diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index af739ba4bc7fd7..9042f945f7f4f4 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -2444,35 +2444,45 @@ def call_test(obj) # When creating bmethods in Ractors, they should only be usable from their # defining ractor, even if it is GC'd assert_equal 'ok', <<~'RUBY' -CLASSES = 1000.times.map { Class.new }.freeze -# This would be better to run in parallel, but there's a bug with lambda -# creation and YJIT causing crashes in dev mode -ractors = CLASSES.map do |klass| - Ractor.new(klass) do |klass| - Ractor.receive - klass.define_method(:foo) {} +begin + CLASSES = 1000.times.map { Class.new }.freeze + + # This would be better to run in parallel, but there's a bug with lambda + # creation and YJIT causing crashes in dev mode + ractors = CLASSES.map do |klass| + Ractor.new(klass) do |klass| + Ractor.receive + klass.define_method(:foo) {} + end end -end -ractors.each do |ractor| - ractor << nil - ractor.join -end + ractors.each do |ractor| + ractor << nil + ractor.join + end -ractors.clear -GC.start + ractors.clear + GC.start -any = 1000.times.map do - Ractor.new do - CLASSES.any? do |klass| - begin - klass.new.foo - true - rescue RuntimeError - false + any = 1000.times.map do + Ractor.new do + CLASSES.any? do |klass| + begin + klass.new.foo + true + rescue RuntimeError + false + end end end + end.map(&:value).none? && :ok +rescue ThreadError => e + # ignore limited memory machine + if /can\'t create Thread/ =~ e.message + :ok + else + raise end -end.map(&:value).none? && :ok +end RUBY diff --git a/ext/win32/resolv/resolv.c b/ext/win32/resolv/resolv.c index 066856dd984df0..b2d377df9fffc6 100644 --- a/ext/win32/resolv/resolv.c +++ b/ext/win32/resolv/resolv.c @@ -21,7 +21,7 @@ w32error_make_error(DWORD e) FORMAT_MESSAGE_IGNORE_INSERTS, &source, e, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), buffer, sizeof(buffer), NULL)) { - snprintf(buffer, sizeof(buffer), "Unknown Error %u", (unsigned long)e); + snprintf(buffer, sizeof(buffer), "Unknown Error %lu", (unsigned long)e); } p = buffer; while ((p = strpbrk(p, "\r\n")) != NULL) { @@ -149,7 +149,6 @@ reg_each_key(VALUE self) { WCHAR wname[256]; HKEY hkey = DATA_PTR(self); - rb_encoding *utf8 = rb_utf8_encoding(); VALUE k = TypedData_Wrap_Struct(CLASS_OF(self), &hkey_type, NULL); DWORD i, e, n; for (i = 0; n = numberof(wname), (e = RegEnumKeyExW(hkey, i, wname, &n, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS; i++) { @@ -183,11 +182,20 @@ reg_value(VALUE self, VALUE name) e = RegGetValueW(hkey, NULL, wname, RRF_RT_ANY, &type, NULL, &size); if (e == ERROR_FILE_NOT_FOUND) return Qnil; w32error_check(e); +# define get_value_2nd(data, dsize) do { \ + DWORD type2 = type; \ + w32error_check(RegGetValueW(hkey, NULL, wname, RRF_RT_ANY, &type2, data, dsize)); \ + if (type != type2) { \ + rb_raise(rb_eRuntimeError, "registry value type changed %lu -> %lu", \ + (unsigned long)type, (unsigned long)type2); \ + } \ + } while (0) + switch (type) { case REG_DWORD: case REG_DWORD_BIG_ENDIAN: { DWORD d; - if (size != sizeof(d)) rb_raise(rb_eRuntimeError, "invalid size returned: %lu", size); + if (size != sizeof(d)) rb_raise(rb_eRuntimeError, "invalid size returned: %lu", (unsigned long)size); w32error_check(RegGetValueW(hkey, NULL, wname, RRF_RT_REG_DWORD, &type, &d, &size)); if (type == REG_DWORD_BIG_ENDIAN) d = swap_dw(d); return ULONG2NUM(d); @@ -195,38 +203,37 @@ reg_value(VALUE self, VALUE name) case REG_QWORD: { QWORD q; - if (size != sizeof(q)) rb_raise(rb_eRuntimeError, "invalid size returned: %lu", size); + if (size != sizeof(q)) rb_raise(rb_eRuntimeError, "invalid size returned: %lu", (unsigned long)size); w32error_check(RegGetValueW(hkey, NULL, wname, RRF_RT_REG_QWORD, &type, &q, &size)); return ULL2NUM(q); } case REG_SZ: case REG_MULTI_SZ: case REG_EXPAND_SZ: - if (size % sizeof(WCHAR)) rb_raise(rb_eRuntimeError, "invalid size returned: %lu", size); + if (size % sizeof(WCHAR)) rb_raise(rb_eRuntimeError, "invalid size returned: %lu", (unsigned long)size); buffer = ALLOCV_N(char, value_buffer, size); + get_value_2nd(buffer, &size); + if (type == REG_MULTI_SZ) { + const WCHAR *w = (WCHAR *)buffer; + result = rb_ary_new(); + size /= sizeof(WCHAR); + size -= 1; + for (size_t i = 0; i < size; ++i) { + int n = lstrlenW(w+i); + rb_ary_push(result, wchar_to_utf8(w+i, n)); + i += n; + } + } + else { + result = wchar_to_utf8((WCHAR *)buffer, lstrlenW((WCHAR *)buffer)); + } + ALLOCV_END(value_buffer); break; default: result = rb_str_new(0, size); - buffer = RSTRING_PTR(result); - } - w32error_check(RegGetValueW(hkey, NULL, wname, RRF_RT_ANY, &type, buffer, &size)); - switch (type) { - case REG_MULTI_SZ: { - const WCHAR *w = (WCHAR *)buffer; - rb_encoding *utf8 = rb_utf8_encoding(); - result = rb_ary_new(); - size /= sizeof(WCHAR); - size -= 1; - for (size_t i = 0; i < size; ++i) { - int n = lstrlenW(w+i); - rb_ary_push(result, wchar_to_utf8(w+i, n)); - i += n; - } - return result; - } - case REG_SZ: case REG_EXPAND_SZ: - return wchar_to_utf8((WCHAR *)buffer, lstrlenW((WCHAR *)buffer)); - default: - return result; + get_value_2nd(RSTRING_PTR(result), &size); + rb_str_set_len(result, size); + break; } + return result; } void diff --git a/lib/bundler/templates/newgem/lib/newgem.rb.tt b/lib/bundler/templates/newgem/lib/newgem.rb.tt index caf6e32f4abf30..3aedee0d25e92b 100644 --- a/lib/bundler/templates/newgem/lib/newgem.rb.tt +++ b/lib/bundler/templates/newgem/lib/newgem.rb.tt @@ -2,7 +2,7 @@ require_relative "<%= File.basename(config[:namespaced_path]) %>/version" <%- if config[:ext] -%> -require_relative "<%= File.basename(config[:namespaced_path]) %>/<%= config[:underscored_name] %>" +require "<%= File.basename(config[:namespaced_path]) %>/<%= config[:underscored_name] %>" <%- end -%> <%- config[:constant_array].each_with_index do |c, i| -%> diff --git a/spec/bundler/commands/newgem_spec.rb b/spec/bundler/commands/newgem_spec.rb index 1d158726bed6a0..06c226f9e56a17 100644 --- a/spec/bundler/commands/newgem_spec.rb +++ b/spec/bundler/commands/newgem_spec.rb @@ -1681,6 +1681,13 @@ def create_temporary_dir(dir) expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.c")).to exist end + it "generates native extension loading code" do + expect(bundled_app("#{gem_name}/lib/#{gem_name}.rb").read).to include(<<~RUBY) + require_relative "test_gem/version" + require "#{gem_name}/#{gem_name}" + RUBY + end + it "includes rake-compiler, but no Rust related changes" do expect(bundled_app("#{gem_name}/Gemfile").read).to include('gem "rake-compiler"') diff --git a/thread_sync.c b/thread_sync.c index 6cc23f7d87b32d..8967e24e341bad 100644 --- a/thread_sync.c +++ b/thread_sync.c @@ -599,6 +599,8 @@ mutex_sleep_begin(VALUE _arguments) VALUE rb_mutex_sleep(VALUE self, VALUE timeout) { + rb_execution_context_t *ec = GET_EC(); + if (!NIL_P(timeout)) { // Validate the argument: rb_time_interval(timeout); @@ -614,7 +616,7 @@ rb_mutex_sleep(VALUE self, VALUE timeout) VALUE woken = rb_ensure(mutex_sleep_begin, (VALUE)&arguments, mutex_lock_uninterruptible, self); - RUBY_VM_CHECK_INTS_BLOCKING(GET_EC()); + RUBY_VM_CHECK_INTS_BLOCKING(ec); if (!woken) return Qnil; time_t end = time(0) - beg; return TIMET2NUM(end);