aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cru/common/SubProcess.h36
-rw-r--r--include/cru/common/platform/unix/PosixSpawnSubProcess.h2
-rw-r--r--src/common/SubProcess.cpp88
-rw-r--r--src/common/platform/unix/PosixSpawnSubProcess.cpp5
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<std::mutex> 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<std::chrono::milliseconds> 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<PlatformSubProcessBase> 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 <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(
- 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<std::chrono::milliseconds> 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 <unordered_map>
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),