aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/SubProcess.cpp75
1 files changed, 52 insertions, 23 deletions
diff --git a/src/common/SubProcess.cpp b/src/common/SubProcess.cpp
index d69fb973..364cd66e 100644
--- a/src/common/SubProcess.cpp
+++ b/src/common/SubProcess.cpp
@@ -9,66 +9,74 @@ SubProcessException::SubProcessException(String message)
SubProcessException::~SubProcessException() {}
+SubProcessFailedToStartException::SubProcessFailedToStartException(
+ String message)
+ : Exception(std::move(message)) {}
+
+SubProcessFailedToStartException::~SubProcessFailedToStartException() {}
+
PlatformSubProcessBase::PlatformSubProcessBase(
const PlatformSubProcessStartInfo& start_info)
- : auto_delete_(false),
- start_info_(start_info),
- data_lock_(data_mutex_, std::defer_lock),
- process_lock_(process_mutex_, std::defer_lock) {}
+ : start_info_(start_info), process_lock_(process_mutex_, std::defer_lock) {}
PlatformSubProcessBase::~PlatformSubProcessBase() {}
void PlatformSubProcessBase::Start() {
- auto data_lock_guard = CreateDataLockGuard();
+ std::lock_guard lock_guard(process_lock_);
if (status_ != PlatformSubProcessStatus::Prepare) {
- throw SubProcessException(u"Sub-process has already run.");
+ throw SubProcessException(u"The process has already tried to start.");
}
- status_ = PlatformSubProcessStatus::Running;
-
try {
PlatformCreateProcess();
+ status_ = PlatformSubProcessStatus::Running;
+
process_thread_ = std::thread([this] {
- auto process_lock_guard = CreateProcessLockGuard();
- PlatformWaitForProcess();
- auto data_lock_guard = CreateDataLockGuard();
- status_ = PlatformSubProcessStatus::Exited;
+ auto exit_result = PlatformWaitForProcess();
+ {
+ std::lock_guard lock_guard(process_lock_);
+ exit_result_ = std::move(exit_result);
+ status_ = PlatformSubProcessStatus::Exited;
+ }
+ this->process_condition_variable_.notify_all();
});
process_thread_.detach();
} catch (const std::exception& e) {
status_ = PlatformSubProcessStatus::FailedToStart;
+ throw SubProcessFailedToStartException(u"Sub-process failed to start. " +
+ String::FromUtf8(e.what()));
}
}
void PlatformSubProcessBase::Wait(
std::optional<std::chrono::milliseconds> wait_time) {
- auto status = GetStatus();
+ std::lock_guard lock_guard(process_lock_);
- if (status == PlatformSubProcessStatus::Prepare) {
+ if (status_ == PlatformSubProcessStatus::Prepare) {
throw SubProcessException(
u"The process does not start. Can't wait for it.");
}
- if (status == PlatformSubProcessStatus::FailedToStart) {
+ if (status_ == PlatformSubProcessStatus::FailedToStart) {
throw SubProcessException(
u"The process failed to start. Can't wait for it.");
}
- if (status == PlatformSubProcessStatus::Exited) {
+ if (status_ == PlatformSubProcessStatus::Exited) {
return;
}
+ auto predicate = [this] {
+ return status_ == PlatformSubProcessStatus::Exited;
+ };
+
if (wait_time) {
- auto locked = process_lock_.try_lock_for(*wait_time);
- if (locked) {
- process_lock_.unlock();
- }
+ process_condition_variable_.wait_for(process_lock_, *wait_time, predicate);
} else {
- process_lock_.lock();
- process_lock_.unlock();
+ process_condition_variable_.wait(process_lock_, predicate);
}
}
@@ -91,7 +99,28 @@ void PlatformSubProcessBase::Kill() {
}
PlatformSubProcessStatus PlatformSubProcessBase::GetStatus() {
- auto data_lock_guard = CreateDataLockGuard();
+ std::lock_guard data_lock_guard(process_lock_);
return status_;
}
+
+PlatformSubProcessExitResult PlatformSubProcessBase::GetExitResult() {
+ std::lock_guard lock_guard(process_lock_);
+
+ if (status_ == PlatformSubProcessStatus::Prepare) {
+ throw SubProcessException(
+ u"The process does not start. Can't get exit result.");
+ }
+
+ if (status_ == PlatformSubProcessStatus::FailedToStart) {
+ throw SubProcessException(
+ u"The process failed to start. Can't get exit result.");
+ }
+
+ if (status_ == PlatformSubProcessStatus::Running) {
+ throw SubProcessException(
+ u"The process is running. Can't get exit result.");
+ }
+
+ return exit_result_;
+}
} // namespace cru