Skip to content

Commit 8d5b82b

Browse files
committed
io: POSIX implementation tries to get status information on short reads/writes.
Fixes #13413.
1 parent 4d6e0e0 commit 8d5b82b

File tree

1 file changed

+44
-7
lines changed

1 file changed

+44
-7
lines changed

src/io/SDL_iostream.c

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -421,18 +421,36 @@ static size_t SDLCALL fd_read(void *userdata, void *ptr, size_t size, SDL_IOStat
421421
ssize_t bytes;
422422
do {
423423
bytes = read(iodata->fd, ptr, size);
424-
} while (bytes < 0 && errno == EINTR);
424+
} while ((bytes < 0) && (errno == EINTR));
425+
426+
ssize_t result = bytes;
427+
if ((bytes > 0) && (bytes < size)) { // was it a short read, EOF, or error?
428+
// try to read the difference, so we can rule out a short read.
429+
do {
430+
result = read(iodata->fd, ((Uint8 *) ptr) + bytes, size - bytes);
431+
} while ((result < 0) && (errno == EINTR));
432+
433+
if (result > 0) {
434+
bytes += result;
435+
result = bytes;
436+
SDL_assert(bytes <= size);
437+
}
438+
}
425439

426-
if (bytes < 0) {
440+
if (result < 0) {
427441
if (errno == EAGAIN) {
428442
*status = SDL_IO_STATUS_NOT_READY;
429443
} else {
430444
*status = SDL_IO_STATUS_ERROR;
431445
SDL_SetError("Error reading from datastream: %s", strerror(errno));
432446
}
433-
bytes = 0;
434-
} else if (bytes == 0) {
447+
if (bytes < 0) {
448+
bytes = 0;
449+
}
450+
} else if (result == 0) {
435451
*status = SDL_IO_STATUS_EOF;
452+
} else if (result < size) {
453+
*status = SDL_IO_STATUS_NOT_READY;;
436454
}
437455
return (size_t)bytes;
438456
}
@@ -443,17 +461,36 @@ static size_t SDLCALL fd_write(void *userdata, const void *ptr, size_t size, SDL
443461
ssize_t bytes;
444462
do {
445463
bytes = write(iodata->fd, ptr, size);
446-
} while (bytes < 0 && errno == EINTR);
464+
} while ((bytes < 0) && (errno == EINTR));
465+
466+
ssize_t result = bytes;
467+
if ((bytes > 0) && (bytes < size)) { // was it a short write, or error?
468+
// try to write the difference, so we can rule out a short read.
469+
do {
470+
result = write(iodata->fd, ((Uint8 *) ptr) + bytes, size - bytes);
471+
} while ((result < 0) && (errno == EINTR));
472+
473+
if (result > 0) {
474+
bytes += result;
475+
result = bytes;
476+
SDL_assert(bytes <= size);
477+
}
478+
}
447479

448-
if (bytes < 0) {
480+
if (result < 0) {
449481
if (errno == EAGAIN) {
450482
*status = SDL_IO_STATUS_NOT_READY;
451483
} else {
452484
*status = SDL_IO_STATUS_ERROR;
453485
SDL_SetError("Error writing to datastream: %s", strerror(errno));
454486
}
455-
bytes = 0;
487+
if (bytes < 0) {
488+
bytes = 0;
489+
}
490+
} else if (result < size) {
491+
*status = SDL_IO_STATUS_NOT_READY;;
456492
}
493+
457494
return (size_t)bytes;
458495
}
459496

0 commit comments

Comments
 (0)