Skip to content

ci(windows): check_thread_locals.py reads Rust sources as cp1252 — GC structural audits fail before any Windows test runs #7977

Description

@proggeramlug

Symptom

windows-build fails after 27 s at its very first real step, GC structural
audits (Windows)
, before the toolchain is even installed — so every later step
(perry-runtime unit tests, the Windows parity smoke, the VERSIONINFO check, the
COFF trimming test) is skipped. Seen on #7972; the base commit is a769fafc6
and the PR touches only crates/perry-runtime/src/gc/.

self-test: the checker can fail in all six directions
Traceback (most recent call last):
  File "D:\a\perry\perry\scripts\check_thread_locals.py", line 441, in <module>
  File "D:\a\perry\perry\scripts\check_thread_locals.py", line 425, in main
  File "D:\a\perry\perry\scripts\check_thread_locals.py", line 243, in verify
  File "D:\a\perry\perry\scripts\check_thread_locals.py", line 213, in scan
  File "D:\a\perry\perry\scripts\check_thread_locals.py", line 168, in cfg_test_module_files
    return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x8d in position 32475

Cause

cfg_test_module_files reads every .rs file under crates/perry-runtime/src
with a bare path.read_text(). On Windows that defaults to the ANSI code page
(cp1252), which has no mapping for 0x81 / 0x8d / 0x8f / 0x90 / 0x9d — and the
runtime tree has 15 files containing one:

crates/perry-runtime/src/i18n.rs                     offset 31552  0x8d
crates/perry-runtime/src/intl.rs                     offset 70386  0x90
crates/perry-runtime/src/thread.rs                   offset  4704  0x90
crates/perry-runtime/src/temporal/duration.rs        offset  1087  0x9d
crates/perry-runtime/src/intl/duration_format.rs     offset 17349  0x81
… 10 more

i18n.rs is the one the walk reaches first, and the arithmetic confirms it
exactly: it has 923 newlines before offset 31552, and with core.autocrlf
turning each into \r\n on the runner, 31552 + 923 = 32475 — the reported
position, to the byte.

The three sibling audit scripts already pass; #7882 ("make GC structural audits
portable") fixed the other readers, and this one call site was missed.

Fix

src = path.read_text(encoding="utf-8")

in cfg_test_module_files, and an audit of the remaining bare read_text() /
open() calls in scripts/ for the same shape.

Why it needs its own issue

It is not the PR that surfaced it: the walk is over the whole crate and does
not depend on any diff, so the gate is red for every PR whose Windows run
executes the current test.yml. Older open PRs (#7754, #7382) get past this
step and fail later, because their runs predate the step; that difference is what
makes it look PR-specific when it is not.

The gate is also failing in the way CLAUDE.md's "★ Four ways a gate can be unable
to fail" warns about, in mirror image: it now fails so early that the eleven
checks behind it — including the only Windows run of the perry-runtime unit
tests — have not executed on any recent PR at all.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions