Skip to content

fix(benchmark): pin UTF-8 for the native process start identity read - #7745

Open
xiaoan17 wants to merge 1 commit into
loopx-project:mainfrom
xiaoan17:codex/pin-utf8-in-native-codex-process
Open

xiaoan17 wants to merge 1 commit into
loopx-project:mainfrom
xiaoan17:codex/pin-utf8-in-native-codex-process

Conversation

@xiaoan17

Copy link
Copy Markdown
Contributor

Goal and source

main is red on the shared test-shard lane for a reason that has nothing to
do with the runtime path: the repository's own text-I/O guard fails
deterministically.

FAILED tests/test_loopx_text_io_utf8.py::test_shipped_runtime_pins_utf8_for_every_text_file_read_and_write
E       AssertionError: assert ['loopx/capab...rocess.py:71'] == []
E         Left contains one more item: 'loopx/capabilities/benchmark_toolkit/native_codex_process.py:71'

The guard is the acceptance for the #4941 locale bug: every text-mode read or
write in the shipped runtime has to pin UTF-8 explicitly, because an implicit
locale codec reopens that failure. The offending line arrived with the native
process evidence work (#7707, merged as 04c5799b8):

stat = Path(f"/proc/{process.pid}/stat").read_text()

Path.read_text() without a codec uses the process locale, so this read is
exactly the shape the guard exists to reject. The same shard lane reports it
on every branch, including main, which is why the repository's shard runs
are red for everyone at the moment.

The change

One line, pinning the codec the repository already uses everywhere else:

stat = Path(f"/proc/{process.pid}/stat").read_text(encoding="utf-8")

The failure semantics do not change: a process name that is not valid UTF-8
raises UnicodeDecodeError, which is a ValueError, and the existing
except (OSError, ValueError, IndexError) already swallows it and leaves the
start identity unknown — the same outcome the implicit locale codec produced
for a non-UTF-8 locale.

Validation

uv run --extra test python -m pytest tests/test_loopx_text_io_utf8.py -q
    2 passed          (1 failed on the base revision, at the same line)

The guard is the acceptance; no new test is needed, and no other file changes.

Boundary

This changes one call in one file and no behaviour, budget, protocol or state.
It is a repair of the acceptance that main currently fails, so every
branch's shard lane stops carrying that failure. It does not touch the two
other failures observed in the same shard runs
(test_dashboard_launcher_selects_* and
test_native_restart_uses_real_accepted_work_fence_before_app_quit), which
are environment and native-host failures in their own lanes.

The shipped text-I/O guard fails on main for this line, and the shard lane
reports it on every branch:

    tests/test_loopx_text_io_utf8.py::test_shipped_runtime_pins_utf8_for_every_text_file_read_and_write
    E   Left contains one more item: 'loopx/capabilities/benchmark_toolkit/native_codex_process.py:71'

Path.read_text() without a codec uses the process locale, which is exactly the
shape the guard exists to reject. Pin the codec the runtime already uses
everywhere else.

The failure semantics do not change: a process name that is not valid UTF-8
raises UnicodeDecodeError, which is a ValueError, and the existing
except (OSError, ValueError, IndexError) already leaves the start identity
unknown.

Signed-off-by: xiaoan17 <anbc1224@gmail.com>
@xiaoan17

Copy link
Copy Markdown
Contributor Author

The one red check is a main-side flake, not this change

chat-bundle-browser (1) failed on the delegation-search smoke, and
checks failed with it:

page.waitForFunction: Timeout 30000ms exceeded.
    at rows (apps/presentation/dashboard/smoke/delegation-search-browser-smoke.mjs:56:32)

That is not this branch's code. The same smoke fails the same way on main's
own run (41146897061, job 124374451899), and it passes locally on this
branch's base:

node smoke/delegation-search-browser-smoke.mjs
PASS: packaged search, pre-pagination match, count, original conversation,
clear/paging, failure/retry, returned history, stale response, Escape/focus,
workspace isolation, narrow layout, English, source refusal/recovery,
changed-snapshot More and read-only receipts.

Other branches' runs of the same lane succeed, so the smoke is intermittent in
CI — a 30 s wait for the delegation rows on a runner that is carrying the
shared shard lane at the same time.

The change in this branch is a single codec argument on a /proc/<pid>/stat
read inside the native process observation, and it is not on the delegation
search path at all. The lane is left to the maintainers' re-run; no content
change is made for a flake.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant