macOS: Fix async file reader error handling

Should fall back to blocking io if aio fails
This commit is contained in:
TellowKrinkle 2021-06-24 21:41:17 -05:00 committed by tellowkrinkle
parent 1a29a6da1d
commit 87c56ccfc4
2 changed files with 41 additions and 37 deletions

View File

@ -79,7 +79,7 @@ class FlatFileReader : public AsyncFileReader
#elif defined(__POSIX__) #elif defined(__POSIX__)
int m_fd; // TODO OSX don't know if overlap as an equivalent on OSX int m_fd; // TODO OSX don't know if overlap as an equivalent on OSX
struct aiocb m_aiocb; struct aiocb m_aiocb;
bool m_read_in_progress; bool m_async_read_in_progress;
#endif #endif
bool shareWrite; bool shareWrite;

View File

@ -16,10 +16,6 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "AsyncFileReader.h" #include "AsyncFileReader.h"
#if defined(__APPLE__)
#warning Tested on FreeBSD, not OS X. Be very afraid.
#endif
// The aio module has been reported to cause issues with FreeBSD 10.3, so let's // The aio module has been reported to cause issues with FreeBSD 10.3, so let's
// disable it for 10.3 and earlier and hope FreeBSD 11 and onwards is fine. // disable it for 10.3 and earlier and hope FreeBSD 11 and onwards is fine.
// Note: It may be worth checking whether aio provides any performance benefit. // Note: It may be worth checking whether aio provides any performance benefit.
@ -32,7 +28,7 @@ FlatFileReader::FlatFileReader(bool shareWrite) : shareWrite(shareWrite)
{ {
m_blocksize = 2048; m_blocksize = 2048;
m_fd = -1; m_fd = -1;
m_read_in_progress = false; m_async_read_in_progress = false;
} }
FlatFileReader::~FlatFileReader(void) FlatFileReader::~FlatFileReader(void)
@ -61,61 +57,69 @@ void FlatFileReader::BeginRead(void* pBuffer, uint sector, uint count)
u32 bytesToRead = count * m_blocksize; u32 bytesToRead = count * m_blocksize;
#if defined(DISABLE_AIO) m_async_read_in_progress = false;
m_aiocb.aio_nbytes = pread(m_fd, pBuffer, bytesToRead, offset); #ifndef DISABLE_AIO
if (m_aiocb.aio_nbytes != bytesToRead)
m_aiocb.aio_nbytes = -1;
#else
m_aiocb = {0}; m_aiocb = {0};
m_aiocb.aio_fildes = m_fd; m_aiocb.aio_fildes = m_fd;
m_aiocb.aio_offset = offset; m_aiocb.aio_offset = offset;
m_aiocb.aio_nbytes = bytesToRead; m_aiocb.aio_nbytes = bytesToRead;
m_aiocb.aio_buf = pBuffer; m_aiocb.aio_buf = pBuffer;
if (aio_read(&m_aiocb) != 0) { if (aio_read(&m_aiocb) == 0)
{
m_async_read_in_progress = true;
}
else
{
switch (errno)
{
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
if (errno == ENOSYS) case ENOSYS:
Console.Error("AIO read failed: Check the aio kernel module is loaded"); Console.Error("AIO read failed: Check the aio kernel module is loaded");
else break;
Console.Error("AIO read failed: error code %d", errno);
#else
Console.Error("AIO read failed: error code %d\n", errno);
#endif #endif
return; case EAGAIN:
Console.Warning("AIO read failed: Out of resources. Will read synchronously");
break;
default:
Console.Error("AIO read failed: error code %d\n", errno);
break;
}
} }
#endif #endif
m_read_in_progress = true; if (!m_async_read_in_progress)
{
m_aiocb.aio_nbytes = pread(m_fd, pBuffer, bytesToRead, offset);
if (m_aiocb.aio_nbytes != bytesToRead)
m_aiocb.aio_nbytes = -1;
}
} }
int FlatFileReader::FinishRead(void) int FlatFileReader::FinishRead(void)
{ {
#if defined(DISABLE_AIO) if (!m_async_read_in_progress)
m_read_in_progress = false; return m_aiocb.aio_nbytes == (size_t)-1 ? -1 : 1;
return m_aiocb.aio_nbytes == (size_t)-1 ? -1: 1; m_async_read_in_progress = true;
#else
struct aiocb *aiocb_list[] = {&m_aiocb}; struct aiocb *aiocb_list[] = {&m_aiocb};
while (aio_suspend(aiocb_list, 1, nullptr) == -1) while (aio_suspend(aiocb_list, 1, nullptr) == -1 && errno == EINTR)
if (errno != EINTR) ;
break; return aio_return(&m_aiocb) == -1 ? -1 : 1;
m_read_in_progress = false;
return aio_return(&m_aiocb) == -1? -1: 1;
#endif
} }
void FlatFileReader::CancelRead(void) void FlatFileReader::CancelRead(void)
{ {
#if !defined(DISABLE_AIO) if (m_async_read_in_progress)
aio_cancel(m_fd, &m_aiocb); {
#endif aio_cancel(m_fd, &m_aiocb);
m_read_in_progress = false; m_async_read_in_progress = false;
}
} }
void FlatFileReader::Close(void) void FlatFileReader::Close(void)
{ {
if (m_read_in_progress) CancelRead();
CancelRead();
if (m_fd != -1) if (m_fd != -1)
close(m_fd); close(m_fd);