aboutsummaryrefslogtreecommitdiff
path: root/src/common/SubProcess.cpp
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2024-06-24 00:06:25 +0800
committercrupest <crupest@outlook.com>2024-07-21 22:33:50 +0800
commit1e8bb0de0b0b05dc1323520dfa57df1f19b51b83 (patch)
tree225bfbf13ecf1a97e2573c174ee867f7301186be /src/common/SubProcess.cpp
parent5f0d7dc36a7a0091bfc152be9f06730cd08eb4dd (diff)
downloadcru-1e8bb0de0b0b05dc1323520dfa57df1f19b51b83.tar.gz
cru-1e8bb0de0b0b05dc1323520dfa57df1f19b51b83.tar.bz2
cru-1e8bb0de0b0b05dc1323520dfa57df1f19b51b83.zip
fix: a lock bug and add test for Wait.
NEED TEST: BufferStream, AutoReadStream, SubProcess.
Diffstat (limited to 'src/common/SubProcess.cpp')
-rw-r--r--src/common/SubProcess.cpp28
1 files changed, 19 insertions, 9 deletions
diff --git a/src/common/SubProcess.cpp b/src/common/SubProcess.cpp
index 0ffb2387..33926f39 100644
--- a/src/common/SubProcess.cpp
+++ b/src/common/SubProcess.cpp
@@ -15,12 +15,13 @@ using ThisPlatformSubProcessImpl = platform::unix::PosixSpawnSubProcessImpl;
PlatformSubProcess::PlatformSubProcess(
SubProcessStartInfo start_info,
std::shared_ptr<IPlatformSubProcessImpl> impl)
- : state_(new State(std::move(start_info), std::move(impl))) {}
+ : state_(new State(std::move(start_info), std::move(impl))),
+ lock_(state_->mutex, std::defer_lock) {}
PlatformSubProcess::~PlatformSubProcess() {}
void PlatformSubProcess::Start() {
- std::lock_guard lock_guard(this->state_->lock);
+ std::lock_guard lock_guard(this->lock_);
if (this->state_->status != SubProcessStatus::Prepare) {
throw SubProcessException(u"The process has already tried to start.");
@@ -31,7 +32,7 @@ void PlatformSubProcess::Start() {
this->state_->status = SubProcessStatus::Running;
auto thread = std::thread([state = state_] {
- std::lock_guard lock_guard(state->lock);
+ std::unique_lock lock(state->mutex);
state->exit_result = state->impl->PlatformWaitForProcess();
state->status = SubProcessStatus::Exited;
state->condition_variable.notify_all();
@@ -47,7 +48,7 @@ void PlatformSubProcess::Start() {
void PlatformSubProcess::Wait(
std::optional<std::chrono::milliseconds> wait_time) {
- std::lock_guard lock_guard(this->state_->lock);
+ std::lock_guard lock_guard(this->lock_);
if (this->state_->status == SubProcessStatus::Prepare) {
throw SubProcessException(
@@ -68,15 +69,15 @@ void PlatformSubProcess::Wait(
};
if (wait_time) {
- this->state_->condition_variable.wait_for(this->state_->lock, *wait_time,
+ this->state_->condition_variable.wait_for(this->lock_, *wait_time,
predicate);
} else {
- this->state_->condition_variable.wait(this->state_->lock, predicate);
+ this->state_->condition_variable.wait(this->lock_, predicate);
}
}
void PlatformSubProcess::Kill() {
- std::lock_guard lock_guard(this->state_->lock);
+ std::lock_guard lock_guard(this->lock_);
if (this->state_->status == SubProcessStatus::Prepare) {
throw SubProcessException(u"The process does not start. Can't kill it.");
@@ -99,12 +100,12 @@ void PlatformSubProcess::Kill() {
}
SubProcessStatus PlatformSubProcess::GetStatus() {
- std::lock_guard lock_guard(this->state_->lock);
+ std::lock_guard lock_guard(this->lock_);
return this->state_->status;
}
SubProcessExitResult PlatformSubProcess::GetExitResult() {
- std::lock_guard lock_guard(this->state_->lock);
+ std::lock_guard lock_guard(this->lock_);
if (this->state_->status == SubProcessStatus::Prepare) {
throw SubProcessException(
@@ -145,6 +146,15 @@ SubProcess SubProcess::Create(String program, std::vector<String> arguments,
return SubProcess(std::move(start_info));
}
+SubProcessExitResult SubProcess::Call(
+ String program, std::vector<String> arguments,
+ std::unordered_map<String, String> environments) {
+ auto process =
+ Create(std::move(program), std::move(arguments), std::move(environments));
+ process.Wait();
+ return process.GetExitResult();
+}
+
SubProcess::SubProcess(SubProcessStartInfo start_info) {
platform_process_.reset(new PlatformSubProcess(
std::move(start_info), std::make_shared<ThisPlatformSubProcessImpl>()));