diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/SubProcess.cpp | 136 | ||||
-rw-r--r-- | src/common/platform/unix/PosixSpawnSubProcess.cpp | 30 |
2 files changed, 18 insertions, 148 deletions
diff --git a/src/common/SubProcess.cpp b/src/common/SubProcess.cpp index e2738248..69f52d9c 100644 --- a/src/common/SubProcess.cpp +++ b/src/common/SubProcess.cpp @@ -1,140 +1,13 @@ #include "cru/common/SubProcess.h" -#include <exception> -#include "cru/common/Exception.h" -#include "cru/common/log/Logger.h" #ifdef CRU_PLATFORM_UNIX #include "cru/common/platform/unix/PosixSpawnSubProcess.h" #endif -#include <mutex> - namespace cru { -PlatformSubProcessBase::PlatformSubProcessBase(SubProcessStartInfo start_info) - : start_info_(std::move(start_info)), - delete_self_(false), - process_lock_(process_mutex_, std::defer_lock) {} - -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_); - - if (status_ != SubProcessStatus::Prepare) { - throw SubProcessException(u"The process has already tried to start."); - } - - try { - PlatformCreateProcess(); - - status_ = SubProcessStatus::Running; - - process_thread_ = std::thread([this] { - auto exit_result = PlatformWaitForProcess(); - { - std::lock_guard lock_guard(process_lock_); - exit_result_ = std::move(exit_result); - status_ = SubProcessStatus::Exited; - } - this->process_condition_variable_.notify_all(); - if (this->delete_self_) { - delete this; - } - }); - - process_thread_.detach(); - } catch (const std::exception& e) { - status_ = SubProcessStatus::FailedToStart; - throw SubProcessFailedToStartException(u"Sub-process failed to start. " + - String::FromUtf8(e.what())); - } -} - -void PlatformSubProcessBase::Wait( - std::optional<std::chrono::milliseconds> wait_time) { - std::lock_guard lock_guard(process_lock_); - - if (status_ == SubProcessStatus::Prepare) { - throw SubProcessException( - u"The process does not start. Can't wait for it."); - } - - if (status_ == SubProcessStatus::FailedToStart) { - throw SubProcessException( - u"The process failed to start. Can't wait for it."); - } - - if (status_ == SubProcessStatus::Exited) { - return; - } - - auto predicate = [this] { return status_ == SubProcessStatus::Exited; }; - - if (wait_time) { - process_condition_variable_.wait_for(process_lock_, *wait_time, predicate); - } else { - process_condition_variable_.wait(process_lock_, predicate); - } -} - -void PlatformSubProcessBase::Kill() { - std::lock_guard data_lock_guard(process_lock_); - - if (status_ == SubProcessStatus::Prepare) { - throw SubProcessException(u"The process does not start. Can't kill it."); - } - - if (status_ == SubProcessStatus::FailedToStart) { - throw SubProcessException(u"The process failed to start. Can't kill it."); - } - - if (status_ == SubProcessStatus::Exited) { - return; - } - - PlatformKillProcess(); -} - -SubProcessStatus PlatformSubProcessBase::GetStatus() { - std::lock_guard data_lock_guard(process_lock_); - return status_; -} - -SubProcessExitResult PlatformSubProcessBase::GetExitResult() { - std::lock_guard lock_guard(process_lock_); - - if (status_ == SubProcessStatus::Prepare) { - throw SubProcessException( - u"The process does not start. Can't get exit result."); - } - - if (status_ == SubProcessStatus::FailedToStart) { - throw SubProcessException( - u"The process failed to start. Can't get exit result."); - } - - if (status_ == SubProcessStatus::Running) { - throw SubProcessException( - u"The process is running. Can't get exit result."); - } - - 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; +using ThisPlatformSubProcess = platform::unix::PosixSpawnSubProcess; #endif SubProcess SubProcess::Create(String program, std::vector<String> arguments, @@ -147,7 +20,7 @@ SubProcess SubProcess::Create(String program, std::vector<String> arguments, } SubProcess::SubProcess(SubProcessStartInfo start_info) { - platform_process_.reset(new PlatformSubProcess(std::move(start_info))); + platform_process_.reset(new ThisPlatformSubProcess(std::move(start_info))); platform_process_->Start(); } @@ -188,10 +61,7 @@ io::Stream* SubProcess::GetStderrStream() { return platform_process_->GetStderrStream(); } -void SubProcess::Detach() { - auto p = platform_process_.release(); - p->SetDeleteSelfOnExit(true); -} +void SubProcess::Detach() { auto p = platform_process_.release(); } void SubProcess::CheckValid() const { if (!IsValid()) { diff --git a/src/common/platform/unix/PosixSpawnSubProcess.cpp b/src/common/platform/unix/PosixSpawnSubProcess.cpp index 4065d6f6..1e2a84d6 100644 --- a/src/common/platform/unix/PosixSpawnSubProcess.cpp +++ b/src/common/platform/unix/PosixSpawnSubProcess.cpp @@ -14,9 +14,8 @@ #include <unordered_map> namespace cru::platform::unix { -PosixSpawnSubProcess::PosixSpawnSubProcess(SubProcessStartInfo start_info) - : PlatformSubProcessBase(std::move(start_info)), - pid_(0), +PosixSpawnSubProcessImpl::PosixSpawnSubProcessImpl() + : pid_(0), exit_code_(0), stdin_pipe_(UnixPipe::Usage::Send), stdout_pipe_(UnixPipe::Usage::Receive), @@ -34,17 +33,17 @@ PosixSpawnSubProcess::PosixSpawnSubProcess(SubProcessStartInfo start_info) std::make_unique<io::AutoReadStream>(stderr_stream_.get(), false); } -PosixSpawnSubProcess::~PosixSpawnSubProcess() {} +PosixSpawnSubProcessImpl::~PosixSpawnSubProcessImpl() {} -io::Stream* PosixSpawnSubProcess::GetStdinStream() { +io::Stream* PosixSpawnSubProcessImpl::GetStdinStream() { return stdin_stream_.get(); } -io::Stream* PosixSpawnSubProcess::GetStdoutStream() { +io::Stream* PosixSpawnSubProcessImpl::GetStdoutStream() { return stdout_buffer_stream_.get(); } -io::Stream* PosixSpawnSubProcess::GetStderrStream() { +io::Stream* PosixSpawnSubProcessImpl::GetStderrStream() { return stderr_buffer_stream_.get(); } @@ -82,7 +81,8 @@ void DestroyCstrArray(char** argv) { } } // namespace -void PosixSpawnSubProcess::PlatformCreateProcess() { +void PosixSpawnSubProcessImpl::PlatformCreateProcess( + const SubProcessStartInfo& start_info) { int error; auto check_error = [&error](String message) { if (error == 0) return; @@ -127,15 +127,15 @@ void PosixSpawnSubProcess::PlatformCreateProcess() { check_error(u"Failed to set flag POSIX_SPAWN_CLOEXEC_DEFAULT (osx)."); #endif - auto exe = start_info_.program.ToUtf8(); - std::vector<String> arguments{start_info_.program}; - arguments.insert(arguments.cend(), start_info_.arguments.cbegin(), - start_info_.arguments.cend()); + auto exe = start_info.program.ToUtf8(); + std::vector<String> arguments{start_info.program}; + arguments.insert(arguments.cend(), start_info.arguments.cbegin(), + start_info.arguments.cend()); auto argv = CreateCstrArray(arguments); Guard argv_guard([argv] { DestroyCstrArray(argv); }); - auto envp = CreateCstrArray(start_info_.environments); + auto envp = CreateCstrArray(start_info.environments); Guard envp_guard([envp] { DestroyCstrArray(envp); }); error = posix_spawnp(&pid_, exe.c_str(), &file_actions, &attr, argv, envp); @@ -149,7 +149,7 @@ void PosixSpawnSubProcess::PlatformCreateProcess() { check_error(u"Failed to close stderr."); } -SubProcessExitResult PosixSpawnSubProcess::PlatformWaitForProcess() { +SubProcessExitResult PosixSpawnSubProcessImpl::PlatformWaitForProcess() { int wstatus; while (waitpid(pid_, &wstatus, 0) == -1) { @@ -173,7 +173,7 @@ SubProcessExitResult PosixSpawnSubProcess::PlatformWaitForProcess() { } } -void PosixSpawnSubProcess::PlatformKillProcess() { +void PosixSpawnSubProcessImpl::PlatformKillProcess() { int error = kill(pid_, SIGKILL); if (error != 0) { std::unique_ptr<ErrnoException> inner(new ErrnoException({}, errno)); |