Skip to content

st: chunked pread with EINTR retry and honest short-read errors#331

Open
nbeerbower wants to merge 2 commits into
JustVugg:devfrom
nbeerbower:st-pread-full
Open

st: chunked pread with EINTR retry and honest short-read errors#331
nbeerbower wants to merge 2 commits into
JustVugg:devfrom
nbeerbower:st-pread-full

Conversation

@nbeerbower

Copy link
Copy Markdown

Same class of bug you fixed in glm.c for #236, still present in the shared st.h readers β€” plus one you haven't hit yet but we did:

  • a single pread caps at ~2^31 bytes on Linux, so any tensor over 2.1 GB comes back silently truncated, with perror printing ... : Success (short reads don't set errno). We hit this in the field with 2.47 GB bf16 embed/unembed tensors; nothing in st.h guards against it today.
  • no EINTR handling.

st_pread_full loops in ST_PREAD_CHUNK pieces (1 GB default), retries EINTR, and reports offset+progress honestly on failure. All five read sites converted; well-formed files read byte-identically (GLM oracle on this branch: 32/32).

Verification: tests/test_st_pread (added to TEST_BINS) compiles with -DST_PREAD_CHUNK=7 so a 96-byte tensor exercises the multi-chunk loop with exact content checks, and forks a child against a shard truncated after st_init (your init-time bounds check already covers static truncation β€” nice β€” so the pread path only fires when a file shrinks under a live handle), asserting exit(1) with a "short read" message and no "Success". make check 70/70, 0 warnings.

πŸ€– Generated with Claude Code

https://claude.ai/code/session_016KLDCYJSyHxd39ChTr4T27

nbeerbower and others added 2 commits July 16, 2026 15:20
Two latent bugs in every st.h reader, both hit in the field:

 - a single pread caps at ~2^31 bytes on Linux, so any tensor past
   2.1 GB (bf16 embed/unembed tensors of large models qualify) came
   back silently truncated with perror printing '... : Success'
   (errno untouched by a short read) β€” the same misleading-error
   symptom glm.c fixed for its own reads in JustVugg#236;
 - no EINTR retry.

st_pread_full loops in ST_PREAD_CHUNK pieces (1 GB default, override
for tests), retries EINTR, and reports offset + progress on failure.
All five read sites converted; behavior on well-formed files is
byte-identical (GLM oracle re-verified on this branch: 32/32).

tests/test_st_pread builds with -DST_PREAD_CHUNK=7 so a 96-byte tensor
exercises the multi-chunk loop, and forks a child against a shard
truncated after st_init (init's static bounds check means the pread
path only fires when a file shrinks under a live handle) asserting
exit(1) with a 'short read' message and no 'Success'.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ed POSIX

Same fix pattern as test_stops: mkdtemp with a CWD-relative template
(MinGW resolves Windows paths; /tmp is not one), and the fork/pipe/
truncate-based truncation subtest compiles only where those exist β€”
Windows still runs the cross-platform chunk-loop content check.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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