aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--include/winapi/process.hpp4
-rw-r--r--src/process.cpp27
-rw-r--r--test/unit_tests/process.cpp17
3 files changed, 47 insertions, 1 deletions
diff --git a/include/winapi/process.hpp b/include/winapi/process.hpp
index 05411cd..5c9e3c9 100644
--- a/include/winapi/process.hpp
+++ b/include/winapi/process.hpp
@@ -26,8 +26,10 @@ public:
static Process runas(const CommandLine&);
+ bool is_running() const;
void wait() const;
-
+ void terminate(int ec = 0) const;
+ void shut_down(int ec = 0) const;
int get_exit_code() const;
static std::string get_exe_path();
diff --git a/src/process.cpp b/src/process.cpp
index a9f24cc..c5e68d7 100644
--- a/src/process.cpp
+++ b/src/process.cpp
@@ -110,6 +110,22 @@ Process Process::runas(const CommandLine& cmd_line) {
return Process{shell_execute(cmd_line)};
}
+bool Process::is_running() const {
+ const auto ret = ::WaitForSingleObject(static_cast<HANDLE>(m_handle), 0);
+
+ switch (ret) {
+ case WAIT_OBJECT_0:
+ return false;
+ case WAIT_TIMEOUT:
+ return true;
+ case WAIT_FAILED:
+ throw error::windows(GetLastError(), "WaitForSingleObject");
+ default:
+ // Shouldn't happen.
+ throw error::custom(ret, "WaitForSingleObject");
+ }
+}
+
void Process::wait() const {
const auto ret = ::WaitForSingleObject(static_cast<HANDLE>(m_handle), INFINITE);
@@ -124,6 +140,17 @@ void Process::wait() const {
}
}
+void Process::terminate(int ec) const {
+ if (!::TerminateProcess(static_cast<HANDLE>(m_handle), static_cast<UINT>(ec))) {
+ throw error::windows(GetLastError(), "TerminateProcess");
+ }
+}
+
+void Process::shut_down(int ec) const {
+ terminate(ec);
+ wait();
+}
+
int Process::get_exit_code() const {
DWORD ec = 0;
diff --git a/test/unit_tests/process.cpp b/test/unit_tests/process.cpp
index 715364f..cfc50f4 100644
--- a/test/unit_tests/process.cpp
+++ b/test/unit_tests/process.cpp
@@ -15,6 +15,8 @@
#include <boost/test/unit_test.hpp>
+#include <chrono>
+#include <thread>
#include <utility>
using namespace winapi;
@@ -89,4 +91,19 @@ BOOST_FIXTURE_TEST_CASE(echo_runas, WithEchoExe) {
BOOST_TEST(process.get_exit_code() == 0);
}
+BOOST_FIXTURE_TEST_CASE(echo_terminate, WithEchoExe) {
+ const CommandLine cmd_line{get_echo_exe()};
+ const auto process = Process::create(cmd_line);
+
+ // echo.exe is stuck trying to read stdin.
+ BOOST_TEST(process.is_running());
+ std::this_thread::sleep_for(std::chrono::seconds{3});
+ BOOST_TEST(process.is_running());
+
+ process.shut_down(123);
+
+ BOOST_TEST(!process.is_running());
+ BOOST_TEST(process.get_exit_code() == 123);
+}
+
BOOST_AUTO_TEST_SUITE_END()