win32: stop erasing the real ReadFile error — pread failures name their WinErr (#307)
compat_pread mapped every non-EOF ReadFile failure to EIO, so the field report was always the same three words: "Input/output error". #307 then burned three rounds of guessing across three people — storage? contention? alignment? — because the actual GetLastError code never appeared anywhere. compat_pread now stashes the code in a per-thread slot and pread_full appends it to the failure line: pread qs: Input/output error (off 780592, 0/8192 bytes, WinErr=1450) That one number is the difference between "insufficient system resources" (1450 -> memory pressure), "sharing violation" (32 -> AV interference), "device not ready" (21 -> the T: drive itself) and a dozen other distinct diagnoses. Diagnostic only: no behavior change, no retry policy — that discussion lives in #361 and should be settled AFTER the first report tells us which error we are actually retrying. Linux path untouched byte-for-byte; the Windows compile is certified by the check.yml MSYS2 job. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -143,6 +143,12 @@ static inline int compat_fadvise(int fd, off_t off, off_t len, int advice){
|
|||||||
* Thread-safe (no shared seek position). Gestisce offset >4 GB e chunking
|
* Thread-safe (no shared seek position). Gestisce offset >4 GB e chunking
|
||||||
* per letture >2 GB (anche se i tensori individuali sono nell'ordine dei
|
* per letture >2 GB (anche se i tensori individuali sono nell'ordine dei
|
||||||
* MB-centinaia di MB, il wrapper e' robusto per ogni taglia). */
|
* MB-centinaia di MB, il wrapper e' robusto per ogni taglia). */
|
||||||
|
/* Ultimo GetLastError() di una ReadFile fallita, per thread: il chiamante
|
||||||
|
* (pread_full in glm.c) lo stampa accanto a strerror. Senza questo, OGNI
|
||||||
|
* fallimento Windows collassa in "EIO -> Input/output error" e la diagnosi
|
||||||
|
* dal campo diventa un tirare a indovinare (#307: tre giri di ipotesi tra
|
||||||
|
* tre persone perche' il codice vero non compariva da nessuna parte). */
|
||||||
|
static __thread DWORD compat_pread_lasterr __attribute__((unused));
|
||||||
static inline ssize_t compat_pread(int fd, void *buf, size_t n, off_t off){
|
static inline ssize_t compat_pread(int fd, void *buf, size_t n, off_t off){
|
||||||
intptr_t osfh = _get_osfhandle(fd);
|
intptr_t osfh = _get_osfhandle(fd);
|
||||||
if(osfh == -1 || osfh == -2){ errno = EBADF; return -1; }
|
if(osfh == -1 || osfh == -2){ errno = EBADF; return -1; }
|
||||||
@@ -158,6 +164,7 @@ static inline ssize_t compat_pread(int fd, void *buf, size_t n, off_t off){
|
|||||||
if(!ReadFile(h, (char*)buf + total, chunk32, &rd, &ov)){
|
if(!ReadFile(h, (char*)buf + total, chunk32, &rd, &ov)){
|
||||||
DWORD err = GetLastError();
|
DWORD err = GetLastError();
|
||||||
if(err == ERROR_HANDLE_EOF) break; /* past EOF → return bytes read (0 if none, matching POSIX pread) */
|
if(err == ERROR_HANDLE_EOF) break; /* past EOF → return bytes read (0 if none, matching POSIX pread) */
|
||||||
|
compat_pread_lasterr = err; /* preserva il codice VERO per il report (#307) */
|
||||||
if(err == ERROR_INVALID_HANDLE || err == ERROR_INVALID_FUNCTION) errno = EBADF;
|
if(err == ERROR_INVALID_HANDLE || err == ERROR_INVALID_FUNCTION) errno = EBADF;
|
||||||
else errno = EIO;
|
else errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -1732,8 +1732,14 @@ static int pread_full(int fd, void *buf, int64_t n, int64_t off, const char *tag
|
|||||||
while(got<n){
|
while(got<n){
|
||||||
ssize_t r=pread(fd, p+got, (size_t)(n-got), off+got);
|
ssize_t r=pread(fd, p+got, (size_t)(n-got), off+got);
|
||||||
if(r<0){ if(errno==EINTR) continue;
|
if(r<0){ if(errno==EINTR) continue;
|
||||||
|
#ifdef _WIN32
|
||||||
|
fprintf(stderr,"%s: %s (off %lld, %lld/%lld bytes, WinErr=%lu)\n",tag,strerror(errno),
|
||||||
|
(long long)off,(long long)got,(long long)n,(unsigned long)compat_pread_lasterr);
|
||||||
|
#else
|
||||||
fprintf(stderr,"%s: %s (off %lld, %lld/%lld bytes)\n",tag,strerror(errno),
|
fprintf(stderr,"%s: %s (off %lld, %lld/%lld bytes)\n",tag,strerror(errno),
|
||||||
(long long)off,(long long)got,(long long)n); return -1; }
|
(long long)off,(long long)got,(long long)n);
|
||||||
|
#endif
|
||||||
|
return -1; }
|
||||||
if(r==0){ fprintf(stderr,"%s: short read at EOF (off %lld, %lld/%lld bytes) — truncated shard?\n",
|
if(r==0){ fprintf(stderr,"%s: short read at EOF (off %lld, %lld/%lld bytes) — truncated shard?\n",
|
||||||
tag,(long long)off,(long long)got,(long long)n); return -1; }
|
tag,(long long)off,(long long)got,(long long)n); return -1; }
|
||||||
got+=r;
|
got+=r;
|
||||||
|
|||||||
Reference in New Issue
Block a user