From 4725b4bc48722356fea4570ed7770137a0999491 Mon Sep 17 00:00:00 2001 From: crupest Date: Sat, 1 Jun 2024 17:09:44 +0800 Subject: HALF WORK: develop SubProcess. --- include/cru/common/SubProcess.h | 36 ++++++++- .../common/platform/unix/PosixSpawnSubProcess.h | 2 +- src/common/SubProcess.cpp | 88 +++++++++++++++++++++- src/common/platform/unix/PosixSpawnSubProcess.cpp | 5 +- 4 files changed, 119 insertions(+), 12 deletions(-) diff --git a/include/cru/common/SubProcess.h b/include/cru/common/SubProcess.h index 9a56b726..0f87b184 100644 --- a/include/cru/common/SubProcess.h +++ b/include/cru/common/SubProcess.h @@ -87,8 +87,10 @@ struct SubProcessExitResult { * process will be killed. */ class PlatformSubProcessBase : public Object { + CRU_DEFINE_CLASS_LOG_TAG(u"PlatformSubProcessBase") + public: - explicit PlatformSubProcessBase(const SubProcessStartInfo& start_info); + explicit PlatformSubProcessBase(SubProcessStartInfo start_info); ~PlatformSubProcessBase() override; @@ -141,6 +143,8 @@ class PlatformSubProcessBase : public Object { virtual io::Stream* GetStdoutStream() = 0; virtual io::Stream* GetStderrStream() = 0; + void SetDeleteSelfOnExit(bool enable); + protected: /** * @brief Create and start a real process. If the program can't be created or @@ -181,6 +185,8 @@ class PlatformSubProcessBase : public Object { private: SubProcessStatus status_; + bool delete_self_; + std::thread process_thread_; std::mutex process_mutex_; std::unique_lock process_lock_; @@ -188,16 +194,38 @@ class PlatformSubProcessBase : public Object { }; class CRU_BASE_API SubProcess : public Object { + CRU_DEFINE_CLASS_LOG_TAG(u"SubProcess") + public: - SubProcess(); + SubProcess(SubProcessStartInfo start_info); CRU_DELETE_COPY(SubProcess) - SubProcess(SubProcess&& other); - SubProcess& operator=(SubProcess&& other); + SubProcess(SubProcess&& other) = default; + SubProcess& operator=(SubProcess&& other) = default; ~SubProcess(); + public: + void Wait(std::optional wait_time); + void Kill(); + + SubProcessStatus GetStatus(); + SubProcessExitResult GetExitResult(); + + io::Stream* GetStdinStream(); + io::Stream* GetStdoutStream(); + io::Stream* GetStderrStream(); + + void Detach(); + + bool IsValid() const { return platform_process_ != nullptr; } + explicit operator bool() const { return IsValid(); } + + private: + void CheckValid() const; + private: + std::unique_ptr platform_process_; }; } // namespace cru diff --git a/include/cru/common/platform/unix/PosixSpawnSubProcess.h b/include/cru/common/platform/unix/PosixSpawnSubProcess.h index e8e23738..249b8043 100644 --- a/include/cru/common/platform/unix/PosixSpawnSubProcess.h +++ b/include/cru/common/platform/unix/PosixSpawnSubProcess.h @@ -18,7 +18,7 @@ class PosixSpawnSubProcess : public PlatformSubProcessBase { CRU_DEFINE_CLASS_LOG_TAG(u"PosixSpawnSubProcess") public: - explicit PosixSpawnSubProcess(const SubProcessStartInfo& start_info); + explicit PosixSpawnSubProcess(SubProcessStartInfo start_info); ~PosixSpawnSubProcess(); io::Stream* GetStdinStream() override; diff --git a/src/common/SubProcess.cpp b/src/common/SubProcess.cpp index ae1c5375..fbe15859 100644 --- a/src/common/SubProcess.cpp +++ b/src/common/SubProcess.cpp @@ -1,14 +1,28 @@ #include "cru/common/SubProcess.h" +#include #include "cru/common/Exception.h" +#include "cru/common/log/Logger.h" + +#ifdef CRU_PLATFORM_UNIX +#include "cru/common/platform/unix/PosixSpawnSubProcess.h" +#endif #include namespace cru { -PlatformSubProcessBase::PlatformSubProcessBase( - const SubProcessStartInfo& start_info) - : start_info_(start_info), process_lock_(process_mutex_, std::defer_lock) {} +PlatformSubProcessBase::PlatformSubProcessBase(SubProcessStartInfo start_info) + : start_info_(std::move(start_info)), + delete_self_(false), + process_lock_(process_mutex_, std::defer_lock) {} -PlatformSubProcessBase::~PlatformSubProcessBase() {} +PlatformSubProcessBase::~PlatformSubProcessBase() { + std::lock_guard lock_guard(process_lock_); + if (status_ == SubProcessStatus::Running) { + CRU_LOG_ERROR( + u"PlatformSubProcessBase is destroyed but process is still running."); + std::terminate(); + } +} void PlatformSubProcessBase::Start() { std::lock_guard lock_guard(process_lock_); @@ -30,6 +44,9 @@ void PlatformSubProcessBase::Start() { status_ = SubProcessStatus::Exited; } this->process_condition_variable_.notify_all(); + if (this->delete_self_) { + delete this; + } }); process_thread_.detach(); @@ -110,4 +127,67 @@ SubProcessExitResult PlatformSubProcessBase::GetExitResult() { return exit_result_; } + +void PlatformSubProcessBase::SetDeleteSelfOnExit(bool enable) { + std::lock_guard lock_guard(process_lock_); + delete_self_ = enable; +} + +#ifdef CRU_PLATFORM_UNIX +using PlatformSubProcess = platform::unix::PosixSpawnSubProcess; +#endif + +SubProcess::SubProcess(SubProcessStartInfo start_info) { + platform_process_.reset(new PlatformSubProcess(std::move(start_info))); + platform_process_->Start(); +} + +SubProcess::~SubProcess() {} + +void SubProcess::Wait(std::optional wait_time) { + CheckValid(); + platform_process_->Wait(wait_time); +} + +void SubProcess::Kill() { + CheckValid(); + platform_process_->Kill(); +} + +SubProcessStatus SubProcess::GetStatus() { + CheckValid(); + return platform_process_->GetStatus(); +} + +SubProcessExitResult SubProcess::GetExitResult() { + CheckValid(); + return platform_process_->GetExitResult(); +} + +io::Stream* SubProcess::GetStdinStream() { + CheckValid(); + return platform_process_->GetStdinStream(); +} + +io::Stream* SubProcess::GetStdoutStream() { + CheckValid(); + return platform_process_->GetStdoutStream(); +} + +io::Stream* SubProcess::GetStderrStream() { + CheckValid(); + return platform_process_->GetStderrStream(); +} + +void SubProcess::Detach() { + auto p = platform_process_.release(); + p->SetDeleteSelfOnExit(true); +} + +void SubProcess::CheckValid() const { + if (!IsValid()) { + throw SubProcessException(u"SubProcess instance is invalid."); + } +} + } // namespace cru diff --git a/src/common/platform/unix/PosixSpawnSubProcess.cpp b/src/common/platform/unix/PosixSpawnSubProcess.cpp index 2528c5ec..9b9a52ae 100644 --- a/src/common/platform/unix/PosixSpawnSubProcess.cpp +++ b/src/common/platform/unix/PosixSpawnSubProcess.cpp @@ -14,9 +14,8 @@ #include namespace cru::platform::unix { -PosixSpawnSubProcess::PosixSpawnSubProcess( - const SubProcessStartInfo& start_info) - : PlatformSubProcessBase(start_info), +PosixSpawnSubProcess::PosixSpawnSubProcess(SubProcessStartInfo start_info) + : PlatformSubProcessBase(std::move(start_info)), pid_(0), exit_code_(0), stdin_pipe_(UnixPipe::Usage::Send), -- cgit v1.2.3