mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-02-13 15:23:34 +00:00
asyncio: don't report failures on closing read-only files with Windows IoRing.
We still need the task to go through the IoRing, even though the flush
operation we use to get it there will always fail on a read-only file. So
check for this specific case and don't report failure.
Fixes #14878.
(cherry picked from commit 4df13e8806)
This commit is contained in:
committed by
Sam Lantinga
parent
de5e0f1784
commit
c3e92cf1c4
@@ -23,20 +23,23 @@
|
||||
#include "SDL_sysasyncio.h"
|
||||
#include "SDL_asyncio_c.h"
|
||||
|
||||
static const char *AsyncFileModeValid(const char *mode)
|
||||
static const char *AsyncFileModeValid(const char *mode, bool *readonly)
|
||||
{
|
||||
static const struct { const char *valid; const char *with_binary; } mode_map[] = {
|
||||
{ "r", "rb" },
|
||||
{ "w", "wb" },
|
||||
{ "r+","r+b" },
|
||||
{ "w+", "w+b" }
|
||||
static const struct { const char *valid; const char *with_binary; bool readonly; } mode_map[] = {
|
||||
{ "r", "rb", true },
|
||||
{ "w", "wb", false },
|
||||
{ "r+","r+b", false },
|
||||
{ "w+", "w+b", false }
|
||||
};
|
||||
|
||||
for (int i = 0; i < SDL_arraysize(mode_map); i++) {
|
||||
if (SDL_strcmp(mode, mode_map[i].valid) == 0) {
|
||||
*readonly = mode_map[i].readonly;
|
||||
return mode_map[i].with_binary;
|
||||
}
|
||||
}
|
||||
|
||||
*readonly = false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -51,7 +54,8 @@ SDL_AsyncIO *SDL_AsyncIOFromFile(const char *file, const char *mode)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *binary_mode = AsyncFileModeValid(mode);
|
||||
bool readonly = false;
|
||||
const char *binary_mode = AsyncFileModeValid(mode, &readonly);
|
||||
if (!binary_mode) {
|
||||
SDL_SetError("Unsupported file mode");
|
||||
return NULL;
|
||||
@@ -62,6 +66,8 @@ SDL_AsyncIO *SDL_AsyncIOFromFile(const char *file, const char *mode)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
asyncio->readonly = readonly;
|
||||
|
||||
asyncio->lock = SDL_CreateMutex();
|
||||
if (!asyncio->lock) {
|
||||
SDL_free(asyncio);
|
||||
|
||||
@@ -124,6 +124,7 @@ struct SDL_AsyncIO
|
||||
SDL_AsyncIOTask tasks;
|
||||
SDL_AsyncIOTask *closing; // The close task, which isn't queued until all pending work for this file is done.
|
||||
bool oneshot; // true if this is a SDL_LoadFileAsync open.
|
||||
bool readonly; // true if this file is opened read-only.
|
||||
};
|
||||
|
||||
// This is implemented for various platforms; param validation is done before calling this. Open file, fill in iface and userdata.
|
||||
|
||||
@@ -200,8 +200,14 @@ static SDL_AsyncIOTask *ProcessCQE(WinIoRingAsyncIOQueueData *queuedata, IORING_
|
||||
task = NULL; // it already finished or was too far along to cancel, so we'll pick up the actual results later.
|
||||
}
|
||||
} else if (FAILED(cqe->ResultCode)) {
|
||||
task->result = SDL_ASYNCIO_FAILURE;
|
||||
// !!! FIXME: fill in task->error.
|
||||
if ((task->type == SDL_ASYNCIO_TASK_CLOSE) && (cqe->ResultCode == E_ACCESSDENIED) && task->asyncio->readonly) {
|
||||
// we push all close requests through as flushes, as there is currently no async close operation and flushing writes to disk is the time-consuming part.
|
||||
// However, flushing a read-only handle generates an error, so we catch this specific situation and ignore it. This approach still makes the task go
|
||||
// through the IoRing so we can handle this all in the same place otherwise. The actual close happens below.
|
||||
} else {
|
||||
task->result = SDL_ASYNCIO_FAILURE;
|
||||
// !!! FIXME: fill in task->error.
|
||||
}
|
||||
} else {
|
||||
if ((task->type == SDL_ASYNCIO_TASK_WRITE) && (((Uint64) cqe->Information) < task->requested_size)) {
|
||||
task->result = SDL_ASYNCIO_FAILURE; // it's always a failure on short writes.
|
||||
|
||||
Reference in New Issue
Block a user