From b58db2ba12d286fc361f91a28d5aac2ffa18292f Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sun, 27 Sep 2026 09:10:20 +0900 Subject: [PATCH 1/5] Give the foreign unshareable store test time to write the crash report The child aborts with [BUG], and symbolizing the C level backtrace for the crash report can take longer than the default 10 seconds on a loaded macOS CI host. Use the same budget as 1712837b7f. https://github.com/ruby/ruby/actions/runs/36230976258 Co-Authored-By: Claude Opus 5.5 --- test/-ext-/gc/test_register.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/-ext-/gc/test_register.rb b/test/-ext-/gc/test_register.rb index 84a069fcad51cd..23fde2a635ea11 100644 --- a/test/-ext-/gc/test_register.rb +++ b/test/-ext-/gc/test_register.rb @@ -148,7 +148,7 @@ def test_verify_internal_consistency_with_ractor_stored_values def test_verify_internal_consistency_fails_on_foreign_unshareable_store omit "needs GC.verify_internal_consistency with the registered-address check" unless GC.respond_to?(:verify_internal_consistency) && Bug::GC.registered_address_check_enabled? - assert_in_out_err([], <<~RUBY, [], /registered address .* changed since registration to an unshareable object owned by another Ractor/, success: false) + assert_in_out_err([], <<~RUBY, [], /registered address .* changed since registration to an unshareable object owned by another Ractor/, success: false, timeout: 60) require '-test-/gc/register' Bug::GC.register_static(0) port = Ractor::Port.new From fa3cbf9e769d5750858ff8ace305ae5ff25be08f Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 16 Sep 2026 21:12:44 +0900 Subject: [PATCH 2/5] Count processors across all processor groups in Etc.nprocessors GetSystemInfo() reports the logical processors of the current processor group only, so Etc.nprocessors returned at most 64 on Windows machines with more than 64 logical processors. GetActiveProcessorCount(ALL_PROCESSOR_GROUPS) counts every group. It is looked up at runtime because mingw-w64 declares it only for _WIN32_WINNT >= 0x0601 while the mingw build targets 0x0600. Co-Authored-By: Claude Fable 5.1 --- ext/etc/etc.c | 19 ++++++++++++++++--- test/etc/test_etc.rb | 3 +++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/ext/etc/etc.c b/ext/etc/etc.c index 627dc92708f445..a1b726bf2aa54d 100644 --- a/ext/etc/etc.c +++ b/ext/etc/etc.c @@ -1074,6 +1074,7 @@ etc_nprocessors_affin(void) * This method is implemented using: * - sched_getaffinity(): Linux * - sysconf(_SC_NPROCESSORS_ONLN): GNU/Linux, NetBSD, FreeBSD, OpenBSD, DragonFly BSD, OpenIndiana, Mac OS X, AIX + * - GetActiveProcessorCount(ALL_PROCESSOR_GROUPS): Windows * * *Example:* * @@ -1112,9 +1113,21 @@ etc_nprocessors(VALUE obj) rb_sys_fail("sysconf(_SC_NPROCESSORS_ONLN)"); } #else - SYSTEM_INFO si; - GetSystemInfo(&si); - ret = (long)si.dwNumberOfProcessors; + /* GetSystemInfo() counts the current processor group only, and GetActiveProcessorCount() is declared only for Windows 7 or later */ + typedef DWORD (WINAPI *GetActiveProcessorCount_t)(WORD); + GetActiveProcessorCount_t pGetActiveProcessorCount = + (GetActiveProcessorCount_t)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetActiveProcessorCount"); + DWORD n = 0; + + if (pGetActiveProcessorCount) { + n = pGetActiveProcessorCount(ALL_PROCESSOR_GROUPS); + } + if (n == 0) { + SYSTEM_INFO si; + GetSystemInfo(&si); + n = si.dwNumberOfProcessors; + } + ret = (long)n; #endif return LONG2NUM(ret); } diff --git a/test/etc/test_etc.rb b/test/etc/test_etc.rb index c2e3af6317ecbb..611832e7899b5d 100644 --- a/test/etc/test_etc.rb +++ b/test/etc/test_etc.rb @@ -167,6 +167,9 @@ def test_pathconf def test_nprocessors n = Etc.nprocessors assert_operator(1, :<=, n) + if /mswin|mingw/ =~ RUBY_PLATFORM + assert_operator(ENV["NUMBER_OF_PROCESSORS"].to_i, :<=, n) + end end def test_sysconfdir From 17af2a8397be34e339aab806ce623adb55994178 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 16 Sep 2026 21:21:07 +0900 Subject: [PATCH 3/5] Define ALL_PROCESSOR_GROUPS for mingw builds mingw-w64 guards the macro with _WIN32_WINNT >= 0x0601 as well as the function, while the mingw build targets 0x0600. Co-Authored-By: Claude Fable 5.1 --- ext/etc/etc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ext/etc/etc.c b/ext/etc/etc.c index a1b726bf2aa54d..7155c88e6fe77f 100644 --- a/ext/etc/etc.c +++ b/ext/etc/etc.c @@ -1113,7 +1113,10 @@ etc_nprocessors(VALUE obj) rb_sys_fail("sysconf(_SC_NPROCESSORS_ONLN)"); } #else - /* GetSystemInfo() counts the current processor group only, and GetActiveProcessorCount() is declared only for Windows 7 or later */ +# ifndef ALL_PROCESSOR_GROUPS +# define ALL_PROCESSOR_GROUPS 0xffff +# endif + /* GetSystemInfo() counts the current processor group only, and mingw-w64 declares GetActiveProcessorCount() only for _WIN32_WINNT >= 0x0601 */ typedef DWORD (WINAPI *GetActiveProcessorCount_t)(WORD); GetActiveProcessorCount_t pGetActiveProcessorCount = (GetActiveProcessorCount_t)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetActiveProcessorCount"); From 41349bb1e8532b4a72ede912c169cf91208ac450 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 16 Sep 2026 21:21:08 +0900 Subject: [PATCH 4/5] Require NUMBER_OF_PROCESSORS in test_nprocessors A missing variable turned the lower bound into 0, which the existing assertion already covers. Co-Authored-By: Claude Fable 5.1 --- test/etc/test_etc.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/etc/test_etc.rb b/test/etc/test_etc.rb index 611832e7899b5d..d0e19f31ceefd6 100644 --- a/test/etc/test_etc.rb +++ b/test/etc/test_etc.rb @@ -168,7 +168,7 @@ def test_nprocessors n = Etc.nprocessors assert_operator(1, :<=, n) if /mswin|mingw/ =~ RUBY_PLATFORM - assert_operator(ENV["NUMBER_OF_PROCESSORS"].to_i, :<=, n) + assert_operator(Integer(ENV.fetch("NUMBER_OF_PROCESSORS")), :<=, n) end end From f6ff9e7d02e46360f8930b280a3dd921cccbda29 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sun, 27 Sep 2026 11:22:57 +0900 Subject: [PATCH 5/5] Etc.uname: Report the actual Windows version GetVersionEx reports 6.2.9200 on Windows 8.1 and later unless the manifest of the executable declares them as supported, and ruby.manifest does not. RtlGetVersion is not affected by the manifest. Co-Authored-By: Claude Opus 5.5 --- ext/etc/etc.c | 8 ++++++-- test/etc/test_etc.rb | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ext/etc/etc.c b/ext/etc/etc.c index 7155c88e6fe77f..1c82c7cda64ad6 100644 --- a/ext/etc/etc.c +++ b/ext/etc/etc.c @@ -800,6 +800,8 @@ static VALUE etc_uname(VALUE obj) { #ifdef _WIN32 + typedef long (WINAPI version_func)(OSVERSIONINFOW *); + version_func *pRtlGetVersion; OSVERSIONINFOW v; SYSTEM_INFO s; const char *sysname, *mach; @@ -808,9 +810,11 @@ etc_uname(VALUE obj) DWORD len = 0; WCHAR *buf; + /* GetVersionEx reports 6.2 unless the manifest declares Windows 8.1 or later */ + pRtlGetVersion = (version_func *)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlGetVersion"); v.dwOSVersionInfoSize = sizeof(v); - if (!GetVersionExW(&v)) - rb_sys_fail("GetVersionEx"); + if (!pRtlGetVersion || pRtlGetVersion(&v)) + rb_notimplement(); result = rb_hash_new(); sysname = "Windows_NT"; diff --git a/test/etc/test_etc.rb b/test/etc/test_etc.rb index d0e19f31ceefd6..39cac7c2fae5a0 100644 --- a/test/etc/test_etc.rb +++ b/test/etc/test_etc.rb @@ -131,6 +131,11 @@ def test_uname } end + def test_uname_release_on_windows + release = IO.popen(%w[cmd.exe /c ver], "rb", &:read)[/\d+\.\d+\.\d+/] + assert_equal(release, Etc.uname[:release]) + end if /mswin|mingw/ =~ RUBY_PLATFORM + def test_sysconf begin Etc.sysconf