[+] WIP internal IO improvements (read: hacks) for Linux + bool IProcess::HasExited()

This commit is contained in:
Reece Wilson 2023-12-24 06:22:58 +00:00
parent 06f54968cd
commit c5656a8843
8 changed files with 135 additions and 8 deletions

View File

@ -30,9 +30,16 @@ namespace Aurora::Processes
*
*/
virtual AuSPtr<IO::Loop::ILoopSource> AsLoopSource() = 0;
/**
* @brief
* @return
*/
virtual bool HasExited() = 0;
/**
* @brief returns the exit code of the process should we outlive them
* @brief returns the exit code of the process should we outlive them.
* undefined if the process has yet to exit.
* @return
*/
virtual AuSInt GetExitCode() = 0;

View File

@ -93,8 +93,19 @@ namespace Aurora::IO::FS
return Loop::ELoopSource::eSourceAIO;
}
LinuxAsyncFileTransaction::LinuxAsyncFileTransaction(AuSPtr<ProcessBlock> pProcessBlock) :
pProcessBlock_(pProcessBlock)
{
}
LinuxAsyncFileTransaction::~LinuxAsyncFileTransaction()
{
if (this->pProcessBlock_)
{
AU_LOCK_GUARD(this->pProcessBlock_->externalLock);
AuTryRemove(this->pProcessBlock_->submits, this);
}
}
void LinuxAsyncFileStream::Init(const AuSPtr<IIOHandle> &handle)
@ -102,9 +113,33 @@ namespace Aurora::IO::FS
this->pHandle_ = handle;
}
void LinuxAsyncFileStream::MakeProcess(Processes::IProcess *pProcess)
{
this->pProcessBlock_ = AuMakeSharedThrow<ProcessBlock>();
this->pProcessBlock_->pProcess = pProcess;
}
void LinuxAsyncFileStream::CheckProcess()
{
if (this->pProcessBlock_)
{
AU_LOCK_GUARD(this->pProcessBlock_->externalLock);
if (this->pProcessBlock_->pProcess &&
this->pProcessBlock_->pProcess->HasExited())
{
this->pProcessBlock_->pProcess = nullptr;
this->pProcessBlock_->bDead = true;
for (auto &pSubmittable : this->pProcessBlock_->submits)
{
pSubmittable->LIOS_Cancel();
}
}
}
}
AuSPtr<IAsyncTransaction> LinuxAsyncFileStream::NewTransaction()
{
auto shared = AuMakeShared<LinuxAsyncFileTransaction>();
auto shared = AuMakeShared<LinuxAsyncFileTransaction>(this->pProcessBlock_);
if (!shared)
{
return {};
@ -115,6 +150,16 @@ namespace Aurora::IO::FS
return {};
}
if (this->pProcessBlock_)
{
AU_LOCK_GUARD(this->pProcessBlock_->externalLock);
if (!AuTryInsert(this->pProcessBlock_->submits, shared.get()))
{
SysPushErrorMemory();
return {};
}
}
return shared;
}
@ -160,6 +205,13 @@ namespace Aurora::IO::FS
}
}
if (this->pProcessBlock_ &&
this->pProcessBlock_->bDead)
{
parameters.outVariable = 0;
return true;
}
if (!PosixSetOffset(fd, offset))
{
return false;
@ -194,6 +246,12 @@ namespace Aurora::IO::FS
return false;
}
if (this->pProcessBlock_ &&
this->pProcessBlock_->bDead)
{
return false;
}
AuUInt32 read;
if (!PosixWrite(fd, parameters.ptr, parameters.length, &read))
{
@ -205,6 +263,10 @@ namespace Aurora::IO::FS
bool LinuxAsyncFileTransaction::Init(const AuSPtr<IIOHandle> &handle)
{
if (!handle)
{
return false;
}
this->pHandle_ = handle;
this->loopSource_ = AuMakeShared<LinuxAsyncFileTransactionLoopSource>(AuSharedFromThis());
return bool(this->loopSource_);
@ -263,6 +325,13 @@ namespace Aurora::IO::FS
}
}
if (this->pProcessBlock_ &&
this->pProcessBlock_->bDead)
{
LIOS_SendProcess(0, false, errno);
return true;
}
offset += this->uBaseOffset;
if (!UNIX::LinuxOverlappedSubmitRead(fd, offset, this, this->loopSource_.get(), bool(IPC_PIPE)))
@ -320,6 +389,13 @@ namespace Aurora::IO::FS
LIOS_Init(AuSharedFromThis());
SetMemory(memoryView);
if (this->pProcessBlock_ &&
this->pProcessBlock_->bDead)
{
LIOS_SendProcess(0, false, errno);
return true;
}
offset += this->uBaseOffset;
if (!UNIX::LinuxOverlappedSubmitWrite(fd, offset, this, this->loopSource_.get()))
@ -447,7 +523,7 @@ namespace Aurora::IO::FS
AUKN_SYM IAsyncFileStream *OpenAsyncNew(const AuString &path, EFileOpenMode openMode, bool bDirectIO, EFileAdvisoryLockLevel lock)
{
auto pHandle = AuIO::IOHandleShared();
auto pHandle = AuIO::IOHandleShared();
if (!pHandle)
{
SysPushErrorMemory();

View File

@ -17,6 +17,14 @@ namespace Aurora::IO::FS
struct LinuxAsyncFileTransaction;
struct LinuxAsyncFileTransactionLoopSource;
struct ProcessBlock
{
AuMutex externalLock;
Processes::IProcess *pProcess;
AuList<Aurora::IO::UNIX::ASubmittable *> submits;
bool bDead {};
};
struct LinuxAsyncFileStream : IAsyncFileStream
{
AuSPtr<IAsyncTransaction> NewTransaction() override;
@ -26,15 +34,19 @@ namespace Aurora::IO::FS
void Init(const AuSPtr<IIOHandle> &handle);
AuSPtr<IIOHandle> GetHandle();
void CheckProcess();
void MakeProcess(Processes::IProcess *pProcess);
AuSPtr<IIOHandle> GetHandle();
private:
AuSPtr<ProcessBlock> pProcessBlock_;
AuSPtr<IIOHandle> pHandle_;
};
struct LinuxAsyncFileTransaction : IAsyncTransaction, AuEnableSharedFromThis<LinuxAsyncFileTransaction>, Aurora::IO::UNIX::ASubmittable
{
LinuxAsyncFileTransaction(AuSPtr<ProcessBlock> pProcessBlock);
~LinuxAsyncFileTransaction();
bool Init(const AuSPtr<IIOHandle> &handle);

View File

@ -362,6 +362,8 @@ namespace Aurora::IO::UNIX
return false;
}
context->abortContext = io->context;
iocb &submit = context->GetIOCB();
submit.aio_data = context->GetData();
submit.aio_lio_opcode = op;
@ -400,7 +402,7 @@ namespace Aurora::IO::UNIX
}
iocb &submit = context->GetIOCB();
if (io_cancel(io->context, &submit, &result) != 0)
if (io_cancel(context->abortContext, &submit, &result) != 0)
{
if (errno == EAGAIN) // The iocb specified was not canceled
{
@ -428,7 +430,16 @@ namespace Aurora::IO::UNIX
}
context->LIOS_Reset();
context->LIOS_SendProcess(bytesTransacted, bError, iErrNo);
// if we're going out of our way to somewhat support cross-thread aborts, this doesnt matter
// let the higher level api filter the abort/reset call
// we're going to be more sorry if we miss a reset/proces-death/eos callback than we allow the api to perform cross-thread aborts
#if 0
if (context->abortContext == io->context)
{
#endif
context->LIOS_SendProcess(bytesTransacted, bError, iErrNo);
}
return true;
}

View File

@ -41,6 +41,7 @@ namespace Aurora::IO::UNIX
AuUInt64 offset2 {};
int fd2 {};
AuLoop::ILSEvent *optEvent2 {};
aio_context_t abortContext {};
private:
AuUInt64 dataPtr_ {};

View File

@ -19,7 +19,7 @@ namespace Aurora::Processes
bool TermWinEnumProcesses();
bool TryKill() override;
bool HasExited();
bool HasExited() override;
AuUInt GetProcessId() override;

View File

@ -125,9 +125,15 @@ namespace Aurora::Processes
return this->pidt_;
}
bool ProcessImpl::HasExited()
{
return this->bHasExited;
}
void ProcessImpl::ByeLol(AuSInt code)
{
this->exitCode_ = code;
this->bHasExited = true;
if (this->finished_)
{
@ -138,6 +144,16 @@ namespace Aurora::Processes
{
this->loopSource_->Set();
}
if (this->fsStream_)
{
this->fsStream_->CheckProcess();
}
if (this->fsErrorStream_)
{
this->fsErrorStream_->CheckProcess();
}
}
void ProcessImpl::ShutdownPipes()
@ -438,6 +454,7 @@ namespace Aurora::Processes
this->fsHandle_->InitFromPairMove(this->pipeStdOut_[0] == -1 ? AuOptionalEx<AuUInt64> {} : AuOptionalEx<AuUInt64> { (AuUInt64)this->pipeStdOut_[0] } ,
this->pipeStdIn_[1] == -1 ? AuOptionalEx<AuUInt64> {} : AuOptionalEx<AuUInt64> { (AuUInt64)this->pipeStdIn_[1] });
this->fsStream_->Init(this->fsHandle_);
this->fsStream_->MakeProcess(this);
}
if (this->startup_.fwdErr == EStreamForward::eAsyncPipe)
@ -456,6 +473,7 @@ namespace Aurora::Processes
this->fsErrorHandle_->InitFromPairMove(this->pipeStdErr_[0] == -1 ? AuOptionalEx<AuUInt64> {} : AuOptionalEx<AuUInt64> { (AuUInt64)this->pipeStdErr_[0] }, {});
this->fsErrorStream_->Init(this->fsErrorHandle_);
this->fsErrorStream_->MakeProcess(this);
}
return true;

View File

@ -32,6 +32,7 @@ namespace Aurora::Processes
void ShutdownPipes();
bool HasExited() override;
bool TryKill() override;
bool Terminate() override;
AuSPtr<Threading::IWaitable> AsWaitable() override;
@ -89,6 +90,7 @@ namespace Aurora::Processes
pid_t pidt_;
bool alive_ {};
AuSInt exitCode_;
AuSInt exitCode_ {};
bool bHasExited {};
};
}