diff --git a/Include/Aurora/Processes/IProcess.hpp b/Include/Aurora/Processes/IProcess.hpp index dd66f89c..025e1694 100644 --- a/Include/Aurora/Processes/IProcess.hpp +++ b/Include/Aurora/Processes/IProcess.hpp @@ -12,6 +12,12 @@ namespace Aurora::Threading struct IWaitable; } +namespace Aurora::IO::CompletionGroup +{ + struct ICompletionGroup; + struct ICompletionGroupWorkHandle; +} + namespace Aurora::Processes { struct IProcess @@ -125,5 +131,9 @@ namespace Aurora::Processes * @return */ virtual AuSPtr ToStreamWriter() = 0; + + virtual bool TryAttachProcessExitToCompletionGroup(const AuSPtr &pCompletionGroup) = 0; + + virtual IO::CompletionGroup::ICompletionGroupWorkHandle *ToCompletionGroupHandle() = 0; }; } \ No newline at end of file diff --git a/Source/Processes/AuProcess.NT.cpp b/Source/Processes/AuProcess.NT.cpp index c2fe410e..c8eb6d53 100644 --- a/Source/Processes/AuProcess.NT.cpp +++ b/Source/Processes/AuProcess.NT.cpp @@ -121,12 +121,25 @@ namespace Aurora::Processes { DWORD exitCode; + if (this->bHasTerminated) + { + return true; + } + if (!GetExitCodeProcess(this->process_, &exitCode)) { return true; } - return exitCode != STILL_ACTIVE; + if (exitCode != STILL_ACTIVE) + { + this->bHasTerminated = true; + return true; + } + else + { + return false; + } } bool ProcessImpl::Terminate() @@ -748,8 +761,14 @@ namespace Aurora::Processes auto result = GetExitCodeProcess(this->processInfo_.hProcess, &exitCode); if (result) { + this->bHasTerminated = true; this->exitCode_ = exitCode; } + + if (auto pCompletionGroup = this->pCompletionGroup_) + { + pCompletionGroup->TryTrigger(); + } }; @@ -773,6 +792,32 @@ namespace Aurora::Processes return true; } + bool ProcessImpl::TryAttachProcessExitToCompletionGroup(const AuSPtr &pCompletionGroup) + { + if (this->pCompletionGroup_) + { + return false; + } + + this->pCompletionGroup_ = pCompletionGroup; + return true; + } + + IO::CompletionGroup::ICompletionGroupWorkHandle *ProcessImpl::ToCompletionGroupHandle() + { + return this; + } + + bool ProcessImpl::HasCompletedForGCWI() + { + return this->HasExited(); + } + + void ProcessImpl::CleanupForGCWI() + { + AuResetMember(this->pCompletionGroup_); + } + void ProcessImpl::RelOtherHandles() { if (!this->bDontRelOut_) diff --git a/Source/Processes/AuProcess.NT.hpp b/Source/Processes/AuProcess.NT.hpp index c241ca1d..80604942 100644 --- a/Source/Processes/AuProcess.NT.hpp +++ b/Source/Processes/AuProcess.NT.hpp @@ -11,7 +11,9 @@ namespace Aurora::Processes { - struct ProcessImpl : IProcess + struct ProcessImpl : + IProcess, + IO::CompletionGroup::ICompletionGroupWorkItem { ProcessImpl(StartupParameters &¶ms); ~ProcessImpl(); @@ -43,6 +45,12 @@ namespace Aurora::Processes bool Start() override; + bool TryAttachProcessExitToCompletionGroup(const AuSPtr &pCompletionGroup) override; + IO::CompletionGroup::ICompletionGroupWorkHandle *ToCompletionGroupHandle() override; + + bool HasCompletedForGCWI() override; + void CleanupForGCWI() override; + bool Init(); void RestLeakyMem(); void RelOtherHandles(); @@ -81,5 +89,7 @@ namespace Aurora::Processes AuThreads::ThreadUnique_t thread_; HANDLE poke_ {INVALID_HANDLE_VALUE}; AuSInt exitCode_; + bool bHasTerminated {}; + AuSPtr pCompletionGroup_; }; } \ No newline at end of file diff --git a/Source/Processes/AuProcess.Unix.cpp b/Source/Processes/AuProcess.Unix.cpp index 01696bd6..ea65d031 100644 --- a/Source/Processes/AuProcess.Unix.cpp +++ b/Source/Processes/AuProcess.Unix.cpp @@ -154,6 +154,11 @@ namespace Aurora::Processes { this->fsErrorStream_->CheckProcess(); } + + if (auto pCompletionGroup = this->pCompletionGroup_) + { + pCompletionGroup->TryTrigger(); + } } void ProcessImpl::ShutdownPipes() @@ -738,6 +743,32 @@ namespace Aurora::Processes return true; } + bool ProcessImpl::TryAttachProcessExitToCompletionGroup(const AuSPtr &pCompletionGroup) + { + if (this->pCompletionGroup_) + { + return false; + } + + this->pCompletionGroup_ = pCompletionGroup; + return true; + } + + IO::CompletionGroup::ICompletionGroupWorkHandle *ProcessImpl::ToCompletionGroupHandle() + { + return this; + } + + bool ProcessImpl::HasCompletedForGCWI() + { + return this->HasExited(); + } + + void ProcessImpl::CleanupForGCWI() + { + AuResetMember(this->pCompletionGroup_); + } + void ProcessImpl::HookMainDeath() { if (this->type_ == ESpawnType::eSpawnChildProcessWorker) diff --git a/Source/Processes/AuProcess.Unix.hpp b/Source/Processes/AuProcess.Unix.hpp index f3a3f6ff..c381f2d9 100644 --- a/Source/Processes/AuProcess.Unix.hpp +++ b/Source/Processes/AuProcess.Unix.hpp @@ -25,7 +25,9 @@ namespace Aurora::Processes void DeinitUnix(); void InitUnix(); - struct ProcessImpl : IProcess + struct ProcessImpl : + IProcess, + IO::CompletionGroup::ICompletionGroupWorkItem { ProcessImpl(StartupParameters &¶ms); ~ProcessImpl(); @@ -53,6 +55,12 @@ namespace Aurora::Processes AuSPtr ToStreamReader(EStandardHandle stream) override; AuSPtr ToStreamWriter() override; + bool TryAttachProcessExitToCompletionGroup(const AuSPtr &pCompletionGroup) override; + IO::CompletionGroup::ICompletionGroupWorkHandle *ToCompletionGroupHandle() override; + + bool HasCompletedForGCWI() override; + void CleanupForGCWI() override; + bool Start() override; bool Init(); @@ -92,5 +100,7 @@ namespace Aurora::Processes AuSInt exitCode_ {}; bool bHasExited {}; + + AuSPtr pCompletionGroup_; }; } \ No newline at end of file