aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/SubProcess.cpp136
-rw-r--r--src/common/platform/unix/PosixSpawnSubProcess.cpp30
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));