summaryrefslogtreecommitdiff
path: root/boost/process/detail
diff options
context:
space:
mode:
Diffstat (limited to 'boost/process/detail')
-rw-r--r--boost/process/detail/child_decl.hpp76
-rw-r--r--boost/process/detail/config.hpp11
-rw-r--r--boost/process/detail/posix/async_in.hpp4
-rw-r--r--boost/process/detail/posix/async_out.hpp3
-rw-r--r--boost/process/detail/posix/async_pipe.hpp12
-rw-r--r--boost/process/detail/posix/basic_cmd.hpp14
-rw-r--r--boost/process/detail/posix/group_handle.hpp23
-rw-r--r--boost/process/detail/posix/io_context_ref.hpp9
-rw-r--r--boost/process/detail/posix/is_running.hpp57
-rw-r--r--boost/process/detail/posix/search_path.hpp4
-rw-r--r--boost/process/detail/posix/sigchld_service.hpp31
-rw-r--r--boost/process/detail/posix/terminate.hpp16
-rw-r--r--boost/process/detail/posix/wait_for_exit.hpp162
-rw-r--r--boost/process/detail/posix/wait_group.hpp164
-rw-r--r--boost/process/detail/windows/async_pipe.hpp22
-rw-r--r--boost/process/detail/windows/file_descriptor.hpp12
-rw-r--r--boost/process/detail/windows/group_handle.hpp2
-rw-r--r--boost/process/detail/windows/is_running.hpp26
-rw-r--r--boost/process/detail/windows/job_workaround.hpp12
-rw-r--r--boost/process/detail/windows/locale.hpp20
-rw-r--r--boost/process/detail/windows/show_window.hpp10
-rw-r--r--boost/process/detail/windows/terminate.hpp17
-rw-r--r--boost/process/detail/windows/wait_for_exit.hpp140
-rw-r--r--boost/process/detail/windows/wait_group.hpp94
24 files changed, 336 insertions, 605 deletions
diff --git a/boost/process/detail/child_decl.hpp b/boost/process/detail/child_decl.hpp
index 24603ffb45..1b0f51c061 100644
--- a/boost/process/detail/child_decl.hpp
+++ b/boost/process/detail/child_decl.hpp
@@ -103,72 +103,52 @@ public:
bool running()
{
- if (valid() && !_exited())
- {
- int code = -1;
- auto res = boost::process::detail::api::is_running(_child_handle, code);
- if (!res && !_exited())
- _exit_status->store(code);
-
- return res;
- }
- return false;
+ std::error_code ec;
+ bool b = running(ec);
+ boost::process::detail::throw_error(ec, "running error");
+ return b;
}
void terminate()
{
- if (valid() && running())
- boost::process::detail::api::terminate(_child_handle);
-
- _terminated = true;
+ std::error_code ec;
+ terminate(ec);
+ boost::process::detail::throw_error(ec, "terminate error");
}
void wait()
{
- if (!_exited() && valid())
- {
- int exit_code = 0;
- boost::process::detail::api::wait(_child_handle, exit_code);
- _exit_status->store(exit_code);
- }
+ std::error_code ec;
+ wait(ec);
+ boost::process::detail::throw_error(ec, "wait error");
}
template< class Rep, class Period >
- bool wait_for (const std::chrono::duration<Rep, Period>& rel_time)
+ bool wait_for (const std::chrono::duration<Rep, Period>& rel_time)
{
- if (!_exited())
- {
- int exit_code = 0;
- auto b = boost::process::detail::api::wait_for(_child_handle, exit_code, rel_time);
- if (!b)
- return false;
- _exit_status->store(exit_code);
- }
- return true;
+ std::error_code ec;
+ bool b = wait_for(rel_time, ec);
+ boost::process::detail::throw_error(ec, "wait_for error");
+ return b;
}
template< class Clock, class Duration >
bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time )
{
- if (!_exited())
- {
- int exit_code = 0;
- auto b = boost::process::detail::api::wait_until(_child_handle, exit_code, timeout_time);
- if (!b)
- return false;
- _exit_status->store(exit_code);
- }
- return true;
+ std::error_code ec;
+ bool b = wait_until(timeout_time, ec);
+ boost::process::detail::throw_error(ec, "wait_until error");
+ return b;
}
bool running(std::error_code & ec) noexcept
{
if (valid() && !_exited())
{
- int code;
- auto res = boost::process::detail::api::is_running(_child_handle, code, ec);
+ int exit_code = 0;
+ auto res = boost::process::detail::api::is_running(_child_handle, exit_code, ec);
if (!res && !_exited())
- _exit_status->store(code);
+ _exit_status->store(exit_code);
return res;
}
@@ -194,17 +174,9 @@ public:
}
template< class Rep, class Period >
- bool wait_for (const std::chrono::duration<Rep, Period>& rel_time, std::error_code & ec) noexcept
+ bool wait_for (const std::chrono::duration<Rep, Period>& rel_time, std::error_code & ec) noexcept
{
- if (!_exited())
- {
- int exit_code = 0;
- auto b = boost::process::detail::api::wait_for(_child_handle, exit_code, rel_time, ec);
- if (!b)
- return false;
- _exit_status->store(exit_code);
- }
- return true;
+ return wait_until(std::chrono::steady_clock::now() + rel_time, ec);
}
template< class Clock, class Duration >
diff --git a/boost/process/detail/config.hpp b/boost/process/detail/config.hpp
index e668811cd5..dfea2c3bb7 100644
--- a/boost/process/detail/config.hpp
+++ b/boost/process/detail/config.hpp
@@ -82,6 +82,17 @@ inline void throw_last_error()
throw process_error(get_last_error());
}
+inline void throw_error(const std::error_code& ec)
+{
+ if (ec)
+ throw process_error(ec);
+}
+
+inline void throw_error(const std::error_code& ec, const char* msg)
+{
+ if (ec)
+ throw process_error(ec, msg);
+}
template<typename Char> constexpr Char null_char();
template<> constexpr char null_char<char> (){return '\0';}
diff --git a/boost/process/detail/posix/async_in.hpp b/boost/process/detail/posix/async_in.hpp
index 1c1e2f40fb..7e9fb94ebd 100644
--- a/boost/process/detail/posix/async_in.hpp
+++ b/boost/process/detail/posix/async_in.hpp
@@ -85,7 +85,9 @@ struct async_in_buffer : ::boost::process::detail::posix::handler_base_ext,
if (::dup2(pipe->native_source(), STDIN_FILENO) == -1)
exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
- ::close(pipe->native_source());
+ if (pipe->native_source() != STDIN_FILENO)
+ ::close(pipe->native_source());
+ ::close(pipe->native_sink());
}
};
diff --git a/boost/process/detail/posix/async_out.hpp b/boost/process/detail/posix/async_out.hpp
index c448490e67..06fd92e1b1 100644
--- a/boost/process/detail/posix/async_out.hpp
+++ b/boost/process/detail/posix/async_out.hpp
@@ -89,6 +89,8 @@ struct async_out_buffer : ::boost::process::detail::posix::handler_base_ext,
exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
::close(pipe->native_sink());
+ ::close(pipe->native_source());
+
}
};
@@ -161,6 +163,7 @@ struct async_out_future : ::boost::process::detail::posix::handler_base_ext,
exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
::close(pipe->native_sink());
+ ::close(pipe->native_source());
}
};
diff --git a/boost/process/detail/posix/async_pipe.hpp b/boost/process/detail/posix/async_pipe.hpp
index 8f138bdfa3..f27ecfe392 100644
--- a/boost/process/detail/posix/async_pipe.hpp
+++ b/boost/process/detail/posix/async_pipe.hpp
@@ -125,6 +125,18 @@ public:
return _sink.write_some(buffers);
}
+ template<typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept
+ {
+ return _source.read_some(buffers, ec);
+ }
+ template<typename MutableBufferSequence>
+ std::size_t write_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept
+ {
+ return _sink.write_some(buffers, ec);
+ }
+
+
native_handle_type native_source() const {return const_cast<boost::asio::posix::stream_descriptor&>(_source).native_handle();}
native_handle_type native_sink () const {return const_cast<boost::asio::posix::stream_descriptor&>(_sink ).native_handle();}
diff --git a/boost/process/detail/posix/basic_cmd.hpp b/boost/process/detail/posix/basic_cmd.hpp
index eefcc5c53f..326e30dc0b 100644
--- a/boost/process/detail/posix/basic_cmd.hpp
+++ b/boost/process/detail/posix/basic_cmd.hpp
@@ -118,12 +118,8 @@ struct exe_cmd_init<char> : boost::process::detail::api::handler_base_ext
else
exec.exe = &exe.front();
-
- if (!args.empty())
- {
- cmd_impl = make_cmd();
- exec.cmd_line = cmd_impl.data();
- }
+ cmd_impl = make_cmd();
+ exec.cmd_line = cmd_impl.data();
}
static exe_cmd_init exe_args(std::string && exe, std::vector<std::string> && args) {return exe_cmd_init(std::move(exe), std::move(args));}
static exe_cmd_init cmd (std::string && cmd)
@@ -163,8 +159,10 @@ std::vector<char*> exe_cmd_init<char>::make_cmd()
if (!exe.empty())
vec.push_back(&exe.front());
- for (auto & v : args)
- vec.push_back(&v.front());
+ if (!args.empty()) {
+ for (auto & v : args)
+ vec.push_back(&v.front());
+ }
vec.push_back(nullptr);
diff --git a/boost/process/detail/posix/group_handle.hpp b/boost/process/detail/posix/group_handle.hpp
index 856b36a6b0..8df4d39435 100644
--- a/boost/process/detail/posix/group_handle.hpp
+++ b/boost/process/detail/posix/group_handle.hpp
@@ -6,14 +6,13 @@
#ifndef BOOST_PROCESS_DETAIL_POSIX_GROUP_HPP_
#define BOOST_PROCESS_DETAIL_POSIX_GROUP_HPP_
+#include <boost/process/detail/config.hpp>
#include <boost/process/detail/posix/child_handle.hpp>
#include <system_error>
#include <unistd.h>
namespace boost { namespace process { namespace detail { namespace posix {
-
-
struct group_handle
{
pid_t grp = -1;
@@ -26,7 +25,6 @@ struct group_handle
{
}
-
group_handle() = default;
~group_handle() = default;
@@ -38,7 +36,6 @@ struct group_handle
group_handle &operator=(const group_handle & c) = delete;
group_handle &operator=(group_handle && c)
{
-
grp = c.grp;
c.grp = -1;
return *this;
@@ -62,23 +59,14 @@ struct group_handle
bool has(handle_t proc, std::error_code & ec) noexcept
{
return ::getpgid(proc) == grp;
-
}
bool valid() const
{
return grp != -1;
}
-
};
-inline void terminate(group_handle &p)
-{
- if (::killpg(p.grp, SIGKILL) == -1)
- boost::process::detail::throw_last_error("killpg(2) failed");
- p.grp = -1;
-}
-
inline void terminate(group_handle &p, std::error_code &ec) noexcept
{
if (::killpg(p.grp, SIGKILL) == -1)
@@ -89,15 +77,18 @@ inline void terminate(group_handle &p, std::error_code &ec) noexcept
p.grp = -1;
}
+inline void terminate(group_handle &p)
+{
+ std::error_code ec;
+ terminate(p, ec);
+ boost::process::detail::throw_error(ec, "killpg(2) failed in terminate");
+}
inline bool in_group()
{
return true;
}
-
-
}}}}
-
#endif /* BOOST_PROCESS_DETAIL_WINDOWS_GROUP_HPP_ */
diff --git a/boost/process/detail/posix/io_context_ref.hpp b/boost/process/detail/posix/io_context_ref.hpp
index 603fd59a16..6eefee2247 100644
--- a/boost/process/detail/posix/io_context_ref.hpp
+++ b/boost/process/detail/posix/io_context_ref.hpp
@@ -18,6 +18,7 @@
#include <boost/process/detail/posix/sigchld_service.hpp>
+#include <boost/process/detail/posix/is_running.hpp>
#include <functional>
#include <type_traits>
@@ -95,11 +96,11 @@ struct io_context_ref : handler_base_ext
auto & es = exec.exit_status;
auto wh = [funcs, es](int val, const std::error_code & ec)
- {
- es->store(val);
+ {
+ es->store(val);
for (auto & func : funcs)
- func(WEXITSTATUS(val), ec);
- };
+ func(::boost::process::detail::posix::eval_exit_status(val), ec);
+ };
sigchld_service.async_wait(exec.pid, std::move(wh));
}
diff --git a/boost/process/detail/posix/is_running.hpp b/boost/process/detail/posix/is_running.hpp
index e8a009dd22..0d431a9126 100644
--- a/boost/process/detail/posix/is_running.hpp
+++ b/boost/process/detail/posix/is_running.hpp
@@ -13,37 +13,22 @@
namespace boost { namespace process { namespace detail { namespace posix {
-
+// Use the "stopped" state (WIFSTOPPED) to indicate "not terminated".
+// This bit arrangement of status codes is not guaranteed by POSIX, but (according to comments in
+// the glibc <bits/waitstatus.h> header) is the same across systems in practice.
constexpr int still_active = 0x7F;
-static_assert(!WIFEXITED(still_active), "Internal Error");
+static_assert(!WIFEXITED(still_active) && !WIFSIGNALED(still_active), "Internal Error");
-inline bool is_running(const child_handle &p, int & exit_code)
+inline bool is_running(int code)
{
- int status;
- auto ret = ::waitpid(p.pid, &status, WNOHANG|WUNTRACED);
-
- if (ret == -1)
- {
- if (errno != ECHILD) //because it no child is running, than this one isn't either, obviously.
- ::boost::process::detail::throw_last_error("is_running error");
-
- return false;
- }
- else if (ret == 0)
- return true;
- else //exited
- {
- if (WIFEXITED(status))
- exit_code = status;
- return false;
- }
+ return !WIFEXITED(code) && !WIFSIGNALED(code);
}
inline bool is_running(const child_handle &p, int & exit_code, std::error_code &ec) noexcept
{
int status;
- auto ret = ::waitpid(p.pid, &status, WNOHANG|WUNTRACED);
-
+ auto ret = ::waitpid(p.pid, &status, WNOHANG);
+
if (ret == -1)
{
if (errno != ECHILD) //because it no child is running, than this one isn't either, obviously.
@@ -55,22 +40,36 @@ inline bool is_running(const child_handle &p, int & exit_code, std::error_code &
else
{
ec.clear();
-
- if (WIFEXITED(status))
+
+ if (!is_running(status))
exit_code = status;
-
+
return false;
}
}
-inline bool is_running(int code)
+inline bool is_running(const child_handle &p, int & exit_code)
{
- return !WIFEXITED(code);
+ std::error_code ec;
+ bool b = is_running(p, exit_code, ec);
+ boost::process::detail::throw_error(ec, "waitpid(2) failed in is_running");
+ return b;
}
inline int eval_exit_status(int code)
{
- return WEXITSTATUS(code);
+ if (WIFEXITED(code))
+ {
+ return WEXITSTATUS(code);
+ }
+ else if (WIFSIGNALED(code))
+ {
+ return WTERMSIG(code);
+ }
+ else
+ {
+ return code;
+ }
}
}}}}
diff --git a/boost/process/detail/posix/search_path.hpp b/boost/process/detail/posix/search_path.hpp
index 633cf0702e..ad781e57d8 100644
--- a/boost/process/detail/posix/search_path.hpp
+++ b/boost/process/detail/posix/search_path.hpp
@@ -27,7 +27,9 @@ inline boost::filesystem::path search_path(
for (const boost::filesystem::path & pp : path)
{
auto p = pp / filename;
- if (!::access(p.c_str(), X_OK))
+ boost::system::error_code ec;
+ bool file = boost::filesystem::is_regular_file(p, ec);
+ if (!ec && file && ::access(p.c_str(), X_OK) == 0)
return p;
}
return "";
diff --git a/boost/process/detail/posix/sigchld_service.hpp b/boost/process/detail/posix/sigchld_service.hpp
index 7fee01e075..108b2b3fba 100644
--- a/boost/process/detail/posix/sigchld_service.hpp
+++ b/boost/process/detail/posix/sigchld_service.hpp
@@ -77,19 +77,28 @@ void sigchld_service::_handle_signal(const boost::system::error_code & ec)
r.second(-1, ec_);
return;
}
- int status;
- int pid = ::waitpid(0, &status, WNOHANG);
- auto itr = std::find_if(_receivers.begin(), _receivers.end(),
- [&pid](const std::pair<::pid_t, std::function<void(int, std::error_code)>> & p)
- {
- return p.first == pid;
- });
- if (itr != _receivers.cend())
- {
- _strand.get_io_context().wrap(itr->second)(status, ec_);
- _receivers.erase(itr);
+ for (auto & r : _receivers) {
+ int status;
+ int pid = ::waitpid(r.first, &status, WNOHANG);
+ if (pid < 0) {
+ // error (eg: the process no longer exists)
+ r.second(-1, get_last_error());
+ r.first = 0; // mark for deletion
+ } else if (pid == r.first) {
+ r.second(status, ec_);
+ r.first = 0; // mark for deletion
+ }
+ // otherwise the process is still around
}
+
+ _receivers.erase(std::remove_if(_receivers.begin(), _receivers.end(),
+ [](const std::pair<::pid_t, std::function<void(int, std::error_code)>> & p)
+ {
+ return p.first == 0;
+ }),
+ _receivers.end());
+
if (!_receivers.empty())
{
_signal_set.async_wait(
diff --git a/boost/process/detail/posix/terminate.hpp b/boost/process/detail/posix/terminate.hpp
index d8048362b0..84024a5b34 100644
--- a/boost/process/detail/posix/terminate.hpp
+++ b/boost/process/detail/posix/terminate.hpp
@@ -19,15 +19,6 @@
namespace boost { namespace process { namespace detail { namespace posix {
-
-inline void terminate(const child_handle &p)
-{
- if (::kill(p.pid, SIGKILL) == -1)
- boost::process::detail::throw_last_error("kill(2) failed");
- int status;
- ::waitpid(p.pid, &status, 0); //just to clean it up
-}
-
inline void terminate(const child_handle &p, std::error_code &ec) noexcept
{
if (::kill(p.pid, SIGKILL) == -1)
@@ -39,6 +30,13 @@ inline void terminate(const child_handle &p, std::error_code &ec) noexcept
::waitpid(p.pid, &status, 0); //just to clean it up
}
+inline void terminate(const child_handle &p)
+{
+ std::error_code ec;
+ terminate(p, ec);
+ boost::process::detail::throw_error(ec, "kill(2) failed");
+}
+
}}}}
#endif
diff --git a/boost/process/detail/posix/wait_for_exit.hpp b/boost/process/detail/posix/wait_for_exit.hpp
index 308aaf6908..21e277baea 100644
--- a/boost/process/detail/posix/wait_for_exit.hpp
+++ b/boost/process/detail/posix/wait_for_exit.hpp
@@ -19,21 +19,6 @@
namespace boost { namespace process { namespace detail { namespace posix {
-inline void wait(const child_handle &p, int & exit_code)
-{
- pid_t ret;
- int status;
- do
- {
- ret = ::waitpid(p.pid, &status, 0);
- } while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status) && !WIFSIGNALED(status)));
- if (ret == -1)
- boost::process::detail::throw_last_error("waitpid(2) failed");
- if (WIFSIGNALED(status))
- throw process_error(std::error_code(), "process terminated due to receipt of a signal");
- exit_code = status;
-}
-
inline void wait(const child_handle &p, int & exit_code, std::error_code &ec) noexcept
{
pid_t ret;
@@ -44,7 +29,7 @@ inline void wait(const child_handle &p, int & exit_code, std::error_code &ec) no
ret = ::waitpid(p.pid, &status, 0);
}
while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status) && !WIFSIGNALED(status)));
-
+
if (ret == -1)
ec = boost::process::detail::get_last_error();
else
@@ -52,60 +37,25 @@ inline void wait(const child_handle &p, int & exit_code, std::error_code &ec) no
ec.clear();
exit_code = status;
}
-
-
}
-template< class Rep, class Period >
-inline bool wait_for(
- const child_handle &p,
- int & exit_code,
- const std::chrono::duration<Rep, Period>& rel_time)
+inline void wait(const child_handle &p, int & exit_code) noexcept
{
-
- pid_t ret;
- int status;
-
- auto start = std::chrono::system_clock::now();
- auto time_out = start + rel_time;
-
- bool timed_out;
- do
- {
- ret = ::waitpid(p.pid, &status, WNOHANG);
- if (ret == 0)
- {
- timed_out = std::chrono::system_clock::now() >= time_out;
- if (timed_out)
- return false;
- }
- }
- while ((ret == 0) ||
- ((ret == -1) && errno == EINTR) ||
- ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status)));
-
- if (ret == -1)
- boost::process::detail::throw_last_error("waitpid(2) failed");
-
- exit_code = status;
-
- return true;
+ std::error_code ec;
+ wait(p, exit_code, ec);
+ boost::process::detail::throw_error(ec, "waitpid(2) failed in wait");
}
-
-template< class Rep, class Period >
-inline bool wait_for(
+template< class Clock, class Duration >
+inline bool wait_until(
const child_handle &p,
int & exit_code,
- const std::chrono::duration<Rep, Period>& rel_time,
+ const std::chrono::time_point<Clock, Duration>& time_out,
std::error_code & ec) noexcept
{
-
pid_t ret;
int status;
- auto start = std::chrono::system_clock::now();
- auto time_out = start + rel_time;
bool timed_out;
do
@@ -113,19 +63,15 @@ inline bool wait_for(
ret = ::waitpid(p.pid, &status, WNOHANG);
if (ret == 0)
{
- timed_out = std::chrono::system_clock::now() >= time_out;
+ timed_out = Clock::now() >= time_out;
if (timed_out)
return false;
}
- }
+ }
while ((ret == 0) ||
(((ret == -1) && errno == EINTR) ||
((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))));
-
- if (timed_out && (ret == -1))
- return false;
-
if (ret == -1)
ec = boost::process::detail::get_last_error();
else
@@ -137,86 +83,38 @@ inline bool wait_for(
return true;
}
-
-
template< class Clock, class Duration >
inline bool wait_until(
const child_handle &p,
int & exit_code,
- const std::chrono::time_point<Clock, Duration>& time_out)
+ const std::chrono::time_point<Clock, Duration>& time_out) noexcept
{
-
- pid_t ret;
- int status;
-
- bool timed_out;
- do
- {
- ret = ::waitpid(p.pid, &status, WNOHANG);
- if (ret == 0)
- {
- timed_out = std::chrono::system_clock::now() >= time_out;
- if (timed_out)
- return false;
- }
- }
- while ((ret == 0) ||
- (((ret == -1) && errno == EINTR) ||
- ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))));
-
-
- if (timed_out && !WIFEXITED(status))
- return false;
-
- if (ret == -1)
- boost::process::detail::throw_last_error("waitpid(2) failed");
- exit_code = status;
-
- return true;
+ std::error_code ec;
+ bool b = wait_until(p, exit_code, time_out, ec);
+ boost::process::detail::throw_error(ec, "waitpid(2) failed in wait_until");
+ return b;
}
-
-template< class Clock, class Duration >
-inline bool wait_until(
+template< class Rep, class Period >
+inline bool wait_for(
const child_handle &p,
int & exit_code,
- const std::chrono::time_point<Clock, Duration>& time_out,
+ const std::chrono::duration<Rep, Period>& rel_time,
std::error_code & ec) noexcept
{
+ return wait_until(p, exit_code, std::chrono::steady_clock::now() + rel_time, ec);
+}
- pid_t ret;
- int status;
-
- bool timed_out;
-
- do
- {
- ret = ::waitpid(p.pid, &status, WNOHANG);
- if (ret == 0)
- {
- timed_out = std::chrono::system_clock::now() >= time_out;
- if (timed_out)
- return false;
- }
- }
- while ((ret == 0) ||
- (((ret == -1) && errno == EINTR) ||
- ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))));
-
-
-
- if (timed_out && !WIFEXITED(status))
- return false;
-
- if (ret == -1)
- ec = boost::process::detail::get_last_error();
- else
- {
- ec.clear();
- exit_code = status;
- }
-
- return true;
+template< class Rep, class Period >
+inline bool wait_for(
+ const child_handle &p,
+ int & exit_code,
+ const std::chrono::duration<Rep, Period>& rel_time) noexcept
+{
+ std::error_code ec;
+ bool b = wait_for(p, exit_code, rel_time, ec);
+ boost::process::detail::throw_error(ec, "waitpid(2) failed in wait_for");
+ return b;
}
}}}}
diff --git a/boost/process/detail/posix/wait_group.hpp b/boost/process/detail/posix/wait_group.hpp
index 172fe06b5b..024d9003b9 100644
--- a/boost/process/detail/posix/wait_group.hpp
+++ b/boost/process/detail/posix/wait_group.hpp
@@ -12,26 +12,13 @@
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/posix/group_handle.hpp>
+#include <chrono>
#include <system_error>
#include <sys/types.h>
#include <sys/wait.h>
namespace boost { namespace process { namespace detail { namespace posix {
-inline void wait(const group_handle &p)
-{
- pid_t ret;
- int status;
- do
- {
- ret = ::waitpid(-p.grp, &status, 0);
- } while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status) && !WIFSIGNALED(status)));
- if (ret == -1)
- boost::process::detail::throw_last_error("waitpid(2) failed");
- if (WIFSIGNALED(status))
- throw process_error(std::error_code(), "process group terminated due to receipt of a signal");
-}
-
inline void wait(const group_handle &p, std::error_code &ec) noexcept
{
pid_t ret;
@@ -42,155 +29,82 @@ inline void wait(const group_handle &p, std::error_code &ec) noexcept
ret = ::waitpid(-p.grp, &status, 0);
}
while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status) && !WIFSIGNALED(status)));
-
+
if (ret == -1)
ec = boost::process::detail::get_last_error();
- else if (WIFSIGNALED(status))
- ec = std::make_error_code(std::errc::no_such_process);
else
ec.clear();
-
}
-template< class Rep, class Period >
-inline bool wait_for(
- const group_handle &p,
- const std::chrono::duration<Rep, Period>& rel_time)
+inline void wait(const group_handle &p) noexcept
{
-
- pid_t ret;
- int status;
-
- auto start = std::chrono::system_clock::now();
- auto time_out = start + rel_time;
-
- bool time_out_occured = false;
- do
- {
- ret = ::waitpid(-p.grp, &status, WUNTRACED | WNOHANG);
- if (std::chrono::system_clock::now() >= time_out)
- {
- time_out_occured = true;
- break;
- }
- }
- while (((ret == -1) && errno == EINTR) ||
- ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status)));
-
-
- if (ret == -1)
- boost::process::detail::throw_last_error("waitpid(2) failed");
- if (WIFSIGNALED(status))
- throw process_error(std::error_code(), "process group terminated due to receipt of a signal");
-
- return !time_out_occured;
+ std::error_code ec;
+ wait(p, ec);
+ boost::process::detail::throw_error(ec, "waitpid(2) failed in wait");
}
-
-template< class Rep, class Period >
-inline bool wait_for(
+template< class Clock, class Duration >
+inline bool wait_until(
const group_handle &p,
- const std::chrono::duration<Rep, Period>& rel_time,
+ const std::chrono::time_point<Clock, Duration>& time_out,
std::error_code & ec) noexcept
{
-
pid_t ret;
int status;
- auto start = std::chrono::system_clock::now();
- auto time_out = start + rel_time;
+ bool timed_out;
- bool time_out_occured = false;
do
{
- ret = ::waitpid(-p.grp, &status, WUNTRACED | WNOHANG);
- if (std::chrono::system_clock::now() >= time_out)
+ ret = ::waitpid(-p.grp, &status, WNOHANG);
+ if (ret == 0)
{
- time_out_occured = true;
- break;
+ timed_out = Clock::now() >= time_out;
+ if (timed_out)
+ return false;
}
- }
- while (((ret == -1) && errno == EINTR) ||
- ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status)));
-
+ }
+ while ((ret == 0) ||
+ (((ret == -1) && errno == EINTR) ||
+ ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))));
if (ret == -1)
ec = boost::process::detail::get_last_error();
- else if (WIFSIGNALED(status))
- ec = std::make_error_code(std::errc::no_such_process);
else
ec.clear();
- return !time_out_occured;
+ return true;
}
-
-
-template< class Rep, class Period >
+template< class Clock, class Duration >
inline bool wait_until(
const group_handle &p,
- const std::chrono::duration<Rep, Period>& time_out)
+ const std::chrono::time_point<Clock, Duration>& time_out) noexcept
{
-
- pid_t ret;
- int status;
-
- bool time_out_occured = false;
- do
- {
- ret = ::waitpid(-p.grp, &status, WUNTRACED | WNOHANG);
- if (std::chrono::system_clock::now() >= time_out)
- {
- time_out_occured = true;
- break;
- }
- }
- while (((ret == -1) && errno == EINTR) ||
- ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status)));
-
-
- if (ret == -1)
- boost::process::detail::throw_last_error("waitpid(2) failed");
- if (WIFSIGNALED(status))
- throw process_error(std::error_code(), "process group terminated due to receipt of a signal");
-
-
- return !time_out_occured;
+ std::error_code ec;
+ bool b = wait_until(p, time_out, ec);
+ boost::process::detail::throw_error(ec, "waitpid(2) failed in wait_until");
+ return b;
}
-
template< class Rep, class Period >
-inline bool wait_until(
+inline bool wait_for(
const group_handle &p,
- const std::chrono::duration<Rep, Period>& time_out,
+ const std::chrono::duration<Rep, Period>& rel_time,
std::error_code & ec) noexcept
{
+ return wait_until(p, std::chrono::steady_clock::now() + rel_time, ec);
+}
- pid_t ret;
- int status;
-
- bool time_out_occured = false;
- do
- {
- ret = ::waitpid(-p.grp, &status, WUNTRACED | WNOHANG);
- if (std::chrono::system_clock::now() >= time_out)
- {
- time_out_occured = true;
- break;
- }
- }
- while (((ret == -1) && errno == EINTR) ||
- ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status)));
-
-
- if (ret == -1)
- ec = boost::process::detail::get_last_error();
- else if (WIFSIGNALED(status))
- ec = std::make_error_code(std::errc::no_such_process);
- else
- ec.clear();
-
- return !time_out_occured;
+template< class Rep, class Period >
+inline bool wait_for(
+ const group_handle &p,
+ const std::chrono::duration<Rep, Period>& rel_time) noexcept
+{
+ std::error_code ec;
+ bool b = wait_for(p, rel_time, ec);
+ boost::process::detail::throw_error(ec, "waitpid(2) failed in wait_for");
+ return b;
}
}}}}
diff --git a/boost/process/detail/windows/async_pipe.hpp b/boost/process/detail/windows/async_pipe.hpp
index 6cae1a584f..1bc2c8fec5 100644
--- a/boost/process/detail/windows/async_pipe.hpp
+++ b/boost/process/detail/windows/async_pipe.hpp
@@ -27,7 +27,7 @@ inline std::string make_pipe_name()
auto pid = ::boost::winapi::GetCurrentProcessId();
- static std::atomic_size_t cnt = 0;
+ static std::atomic_size_t cnt{0};
name += std::to_string(pid);
name += "_";
name += std::to_string(cnt++);
@@ -144,6 +144,18 @@ public:
return _sink.write_some(buffers);
}
+
+ template<typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept
+ {
+ return _source.read_some(buffers, ec);
+ }
+ template<typename MutableBufferSequence>
+ std::size_t write_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept
+ {
+ return _sink.write_some(buffers, ec);
+ }
+
native_handle_type native_source() const {return const_cast<boost::asio::windows::stream_handle&>(_source).native_handle();}
native_handle_type native_sink () const {return const_cast<boost::asio::windows::stream_handle&>(_sink ).native_handle();}
@@ -265,7 +277,11 @@ async_pipe::async_pipe(boost::asio::io_context & ios_source,
static constexpr int FILE_FLAG_OVERLAPPED_ = 0x40000000; //temporary
::boost::winapi::HANDLE_ source = ::boost::winapi::create_named_pipe(
+#if defined(BOOST_NO_ANSI_APIS)
+ ::boost::process::detail::convert(name).c_str(),
+#else
name.c_str(),
+#endif
::boost::winapi::PIPE_ACCESS_INBOUND_
| FILE_FLAG_OVERLAPPED_, //write flag
0, 1, 8192, 8192, 0, nullptr);
@@ -277,7 +293,11 @@ async_pipe::async_pipe(boost::asio::io_context & ios_source,
_source.assign(source);
::boost::winapi::HANDLE_ sink = boost::winapi::create_file(
+#if defined(BOOST_NO_ANSI_APIS)
+ ::boost::process::detail::convert(name).c_str(),
+#else
name.c_str(),
+#endif
::boost::winapi::GENERIC_WRITE_, 0, nullptr,
::boost::winapi::OPEN_EXISTING_,
FILE_FLAG_OVERLAPPED_, //to allow read
diff --git a/boost/process/detail/windows/file_descriptor.hpp b/boost/process/detail/windows/file_descriptor.hpp
index 80e4c8ae8f..5058080cc4 100644
--- a/boost/process/detail/windows/file_descriptor.hpp
+++ b/boost/process/detail/windows/file_descriptor.hpp
@@ -45,11 +45,19 @@ struct file_descriptor
}
file_descriptor(const std::string & path , mode_t mode = read_write)
- : file_descriptor(path.c_str(), mode) {}
+#if defined(BOOST_NO_ANSI_APIS)
+ : file_descriptor(::boost::process::detail::convert(path), mode)
+#else
+ : file_descriptor(path.c_str(), mode)
+#endif
+ {}
file_descriptor(const std::wstring & path, mode_t mode = read_write)
: file_descriptor(path.c_str(), mode) {}
file_descriptor(const char* path, mode_t mode = read_write)
+#if defined(BOOST_NO_ANSI_APIS)
+ : file_descriptor(std::string(path), mode)
+#else
: _handle(
::boost::winapi::create_file(
path,
@@ -62,8 +70,8 @@ struct file_descriptor
::boost::winapi::FILE_ATTRIBUTE_NORMAL_,
nullptr
))
+#endif
{
-
}
file_descriptor(const wchar_t * path, mode_t mode = read_write)
: _handle(
diff --git a/boost/process/detail/windows/group_handle.hpp b/boost/process/detail/windows/group_handle.hpp
index 5025c0d245..42b0a9280d 100644
--- a/boost/process/detail/windows/group_handle.hpp
+++ b/boost/process/detail/windows/group_handle.hpp
@@ -103,7 +103,7 @@ struct group_handle
}
- group_handle() : group_handle(::boost::winapi::CreateJobObjectA(nullptr, nullptr))
+ group_handle() : group_handle(::boost::winapi::CreateJobObjectW(nullptr, nullptr))
{
}
diff --git a/boost/process/detail/windows/is_running.hpp b/boost/process/detail/windows/is_running.hpp
index 920693d116..d8e5a6fb7c 100644
--- a/boost/process/detail/windows/is_running.hpp
+++ b/boost/process/detail/windows/is_running.hpp
@@ -18,22 +18,6 @@ constexpr static ::boost::winapi::DWORD_ still_active = 259;
struct child_handle;
-inline bool is_running(const child_handle &p, int & exit_code)
-{
- ::boost::winapi::DWORD_ code;
- //single value, not needed in the winapi.
- if (!::boost::winapi::GetExitCodeProcess(p.process_handle(), &code))
- ::boost::process::detail::throw_last_error("GetExitCodeProcess() failed");
-
- if (code == still_active)
- return true;
- else
- {
- exit_code = code;
- return false;
- }
-}
-
inline bool is_running(const child_handle &p, int & exit_code, std::error_code &ec) noexcept
{
::boost::winapi::DWORD_ code;
@@ -49,7 +33,15 @@ inline bool is_running(const child_handle &p, int & exit_code, std::error_code &
{
exit_code = code;
return false;
- }
+ }
+}
+
+inline bool is_running(const child_handle &p, int & exit_code)
+{
+ std::error_code ec;
+ bool b = is_running(p, exit_code, ec);
+ boost::process::detail::throw_error(ec, "GetExitCodeProcess() failed in is_running");
+ return b;
}
inline bool is_running(int code)
diff --git a/boost/process/detail/windows/job_workaround.hpp b/boost/process/detail/windows/job_workaround.hpp
index 16534ce003..574e406609 100644
--- a/boost/process/detail/windows/job_workaround.hpp
+++ b/boost/process/detail/windows/job_workaround.hpp
@@ -82,7 +82,7 @@ typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ {
_Out_opt_ LPDWORD lpReturnLength
);
*/
-typedef ::boost::winapi::BOOL_ ( WINAPI *query_information_job_object_p)(
+typedef ::boost::winapi::BOOL_ (*query_information_job_object_p)(
::boost::winapi::HANDLE_,
JOBOBJECTINFOCLASS_,
void *,
@@ -90,14 +90,14 @@ typedef ::boost::winapi::BOOL_ ( WINAPI *query_information_job_object_p)(
::boost::winapi::DWORD_ *);
-inline ::boost::winapi::BOOL_ WINAPI query_information_job_object(
+inline ::boost::winapi::BOOL_ query_information_job_object(
::boost::winapi::HANDLE_ hJob,
JOBOBJECTINFOCLASS_ JobObjectInfoClass,
void * lpJobObjectInfo,
::boost::winapi::DWORD_ cbJobObjectInfoLength,
::boost::winapi::DWORD_ *lpReturnLength)
{
- static ::boost::winapi::HMODULE_ h = ::boost::winapi::get_module_handle("Kernel32.dll");
+ static ::boost::winapi::HMODULE_ h = ::boost::winapi::get_module_handle(L"Kernel32.dll");
static query_information_job_object_p f = reinterpret_cast<query_information_job_object_p>(::boost::winapi::get_proc_address(h, "QueryInformationJobObject"));
return (*f)(hJob, JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength, lpReturnLength);
@@ -110,7 +110,7 @@ inline ::boost::winapi::BOOL_ WINAPI query_information_job_object(
_In_ DWORD cbJobObjectInfoLength
);*/
-typedef ::boost::winapi::BOOL_ ( WINAPI *set_information_job_object_p)(
+typedef ::boost::winapi::BOOL_ (*set_information_job_object_p)(
::boost::winapi::HANDLE_,
JOBOBJECTINFOCLASS_,
void *,
@@ -118,13 +118,13 @@ typedef ::boost::winapi::BOOL_ ( WINAPI *set_information_job_object_p)(
}
-inline ::boost::winapi::BOOL_ WINAPI set_information_job_object(
+inline ::boost::winapi::BOOL_ set_information_job_object(
::boost::winapi::HANDLE_ hJob,
JOBOBJECTINFOCLASS_ JobObjectInfoClass,
void * lpJobObjectInfo,
::boost::winapi::DWORD_ cbJobObjectInfoLength)
{
- static ::boost::winapi::HMODULE_ h = ::boost::winapi::get_module_handle("Kernel32.dll");
+ static ::boost::winapi::HMODULE_ h = ::boost::winapi::get_module_handle(L"Kernel32.dll");
static set_information_job_object_p f = reinterpret_cast<set_information_job_object_p>(::boost::winapi::get_proc_address(h, "SetInformationJobObject"));
return (*f)(hJob, JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength);
diff --git a/boost/process/detail/windows/locale.hpp b/boost/process/detail/windows/locale.hpp
index 90b0110dc5..ee16c6347e 100644
--- a/boost/process/detail/windows/locale.hpp
+++ b/boost/process/detail/windows/locale.hpp
@@ -41,11 +41,15 @@ class windows_file_codecvt
wchar_t* to, wchar_t* to_end, wchar_t*& to_next) const override
{
boost::ignore_unused(state);
- ::boost::winapi::UINT_ codepage = AreFileApisANSI() ?
- ::boost::winapi::CP_ACP_ :
- ::boost::winapi::CP_OEMCP_;
- int count;
+ auto codepage =
+#if !defined(BOOST_NO_ANSI_APIS)
+ ::boost::winapi::AreFileApisANSI() ?
+ ::boost::winapi::CP_ACP_ :
+#endif
+ ::boost::winapi::CP_OEMCP_;
+
+ int count = 0;
if ((count = ::boost::winapi::MultiByteToWideChar(codepage,
::boost::winapi::MB_PRECOMPOSED_, from,
static_cast<int>(from_end - from), to, static_cast<int>(to_end - to))) == 0)
@@ -64,11 +68,15 @@ class windows_file_codecvt
char* to, char* to_end, char*& to_next) const override
{
boost::ignore_unused(state);
- auto codepage = ::boost::winapi::AreFileApisANSI() ?
+ auto codepage =
+#if !defined(BOOST_NO_ANSI_APIS)
+ ::boost::winapi::AreFileApisANSI() ?
::boost::winapi::CP_ACP_ :
+#endif
::boost::winapi::CP_OEMCP_;
+ int count = 0;
+
- int count;
if ((count = ::boost::winapi::WideCharToMultiByte(codepage,
::boost::winapi::WC_NO_BEST_FIT_CHARS_, from,
static_cast<int>(from_end - from), to, static_cast<int>(to_end - to), 0, 0)) == 0)
diff --git a/boost/process/detail/windows/show_window.hpp b/boost/process/detail/windows/show_window.hpp
index 3cd2b44902..8821e0849c 100644
--- a/boost/process/detail/windows/show_window.hpp
+++ b/boost/process/detail/windows/show_window.hpp
@@ -29,8 +29,14 @@ struct show_window : ::boost::process::detail::handler_base
}
};
-
-
+struct create_no_window_ : public ::boost::process::detail::handler_base
+{
+ template <class Executor>
+ void on_setup(Executor &exec) const
+ {
+ exec.creation_flags |= ::boost::detail::winapi::CREATE_NO_WINDOW_;
+ }
+};
}}}}
diff --git a/boost/process/detail/windows/terminate.hpp b/boost/process/detail/windows/terminate.hpp
index ba66e4085c..8a413173da 100644
--- a/boost/process/detail/windows/terminate.hpp
+++ b/boost/process/detail/windows/terminate.hpp
@@ -20,15 +20,6 @@ namespace boost { namespace process { namespace detail { namespace windows {
struct child_handle;
-inline void terminate(child_handle &p)
-{
- if (!::boost::winapi::TerminateProcess(p.process_handle(), EXIT_FAILURE))
- boost::process::detail::throw_last_error("TerminateProcess() failed");
-
- ::boost::winapi::CloseHandle(p.proc_info.hProcess);
- p.proc_info.hProcess = ::boost::winapi::INVALID_HANDLE_VALUE_;
-}
-
inline void terminate(child_handle &p, std::error_code &ec) noexcept
{
if (!::boost::winapi::TerminateProcess(p.process_handle(), EXIT_FAILURE))
@@ -41,8 +32,12 @@ inline void terminate(child_handle &p, std::error_code &ec) noexcept
}
}
-
-
+inline void terminate(child_handle &p)
+{
+ std::error_code ec;
+ terminate(p, ec);
+ boost::process::detail::throw_error(ec, "TerminateProcess() failed in terminate");
+}
}}}}
diff --git a/boost/process/detail/windows/wait_for_exit.hpp b/boost/process/detail/windows/wait_for_exit.hpp
index 4219d9725a..37d24b1aeb 100644
--- a/boost/process/detail/windows/wait_for_exit.hpp
+++ b/boost/process/detail/windows/wait_for_exit.hpp
@@ -20,21 +20,6 @@
namespace boost { namespace process { namespace detail { namespace windows {
-inline void wait(child_handle &p, int & exit_code)
-{
- if (::boost::winapi::WaitForSingleObject(p.process_handle(),
- ::boost::winapi::infinite) == ::boost::winapi::wait_failed)
- throw_last_error("WaitForSingleObject() failed");
-
- ::boost::winapi::DWORD_ _exit_code;
- if (!::boost::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
- throw_last_error("GetExitCodeProcess() failed");
-
- ::boost::winapi::CloseHandle(p.proc_info.hProcess);
- p.proc_info.hProcess = ::boost::winapi::INVALID_HANDLE_VALUE_;
- exit_code = static_cast<int>(_exit_code);
-}
-
inline void wait(child_handle &p, int & exit_code, std::error_code &ec) noexcept
{
::boost::winapi::DWORD_ _exit_code = 1;
@@ -56,64 +41,40 @@ inline void wait(child_handle &p, int & exit_code, std::error_code &ec) noexcept
exit_code = static_cast<int>(_exit_code);
}
-
-template< class Rep, class Period >
-inline bool wait_for(
- child_handle &p,
- int & exit_code,
- const std::chrono::duration<Rep, Period>& rel_time)
+inline void wait(child_handle &p, int & exit_code)
{
-
- std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(rel_time);
-
- ::boost::winapi::DWORD_ wait_code;
- wait_code = ::boost::winapi::WaitForSingleObject(p.process_handle(),
- static_cast<::boost::winapi::DWORD_>(ms.count()));
- if (wait_code == ::boost::winapi::wait_failed)
- throw_last_error("WaitForSingleObject() failed");
- else if (wait_code == ::boost::winapi::wait_timeout)
- return false; //
-
- ::boost::winapi::DWORD_ _exit_code;
- if (!::boost::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
- throw_last_error("GetExitCodeProcess() failed");
-
- exit_code = static_cast<int>(_exit_code);
- ::boost::winapi::CloseHandle(p.proc_info.hProcess);
- p.proc_info.hProcess = ::boost::winapi::INVALID_HANDLE_VALUE_;
- return true;
+ std::error_code ec;
+ wait(p, exit_code, ec);
+ boost::process::detail::throw_error(ec, "wait error");
}
-
-template< class Rep, class Period >
-inline bool wait_for(
+template< class Clock, class Duration >
+inline bool wait_until(
child_handle &p,
int & exit_code,
- const std::chrono::duration<Rep, Period>& rel_time,
+ const std::chrono::time_point<Clock, Duration>& timeout_time,
std::error_code &ec) noexcept
{
-
- std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(rel_time);
-
+ std::chrono::milliseconds ms =
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ timeout_time - Clock::now());
::boost::winapi::DWORD_ wait_code;
wait_code = ::boost::winapi::WaitForSingleObject(p.process_handle(),
- static_cast<::boost::winapi::DWORD_>(ms.count()));
+ static_cast<::boost::winapi::DWORD_>(ms.count()));
+
if (wait_code == ::boost::winapi::wait_failed)
ec = std::error_code(
::boost::winapi::GetLastError(),
std::system_category());
else if (wait_code == ::boost::winapi::wait_timeout)
- return false; //
+ return false;
- ::boost::winapi::DWORD_ _exit_code = 1;
+ ::boost::winapi::DWORD_ _exit_code;
if (!::boost::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
- {
ec = std::error_code(
::boost::winapi::GetLastError(),
std::system_category());
- return false;
- }
else
ec.clear();
@@ -121,7 +82,6 @@ inline bool wait_for(
::boost::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::winapi::INVALID_HANDLE_VALUE_;
return true;
-;
}
template< class Clock, class Duration >
@@ -130,67 +90,33 @@ inline bool wait_until(
int & exit_code,
const std::chrono::time_point<Clock, Duration>& timeout_time)
{
- std::chrono::milliseconds ms =
- std::chrono::duration_cast<std::chrono::milliseconds>(
- timeout_time - std::chrono::system_clock::now());
-
- ::boost::winapi::DWORD_ wait_code;
- wait_code = ::boost::winapi::WaitForSingleObject(p.process_handle(),
- static_cast<::boost::winapi::DWORD_>(ms.count()));
-
- if (wait_code == ::boost::winapi::wait_failed)
- throw_last_error("WaitForSingleObject() failed");
- else if (wait_code == ::boost::winapi::wait_timeout)
- return false;
-
- ::boost::winapi::DWORD_ _exit_code;
- if (!::boost::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
- throw_last_error("GetExitCodeProcess() failed");
-
- exit_code = static_cast<int>(_exit_code);
- ::boost::winapi::CloseHandle(p.proc_info.hProcess);
- p.proc_info.hProcess = ::boost::winapi::INVALID_HANDLE_VALUE_;
- return true;
+ std::error_code ec;
+ bool b = wait_until(p, exit_code, timeout_time, ec);
+ boost::process::detail::throw_error(ec, "wait_until error");
+ return b;
}
-
-template< class Clock, class Duration >
-inline bool wait_until(
+template< class Rep, class Period >
+inline bool wait_for(
child_handle &p,
int & exit_code,
- const std::chrono::time_point<Clock, Duration>& timeout_time,
+ const std::chrono::duration<Rep, Period>& rel_time,
std::error_code &ec) noexcept
{
- std::chrono::milliseconds ms =
- std::chrono::duration_cast<std::chrono::milliseconds>(
- timeout_time - std::chrono::system_clock::now());
-
- ::boost::winapi::DWORD_ wait_code;
- wait_code = ::boost::winapi::WaitForSingleObject(p.process_handle(),
- static_cast<::boost::winapi::DWORD_>(ms.count()));
-
- if (wait_code == ::boost::winapi::wait_failed)
- ec = std::error_code(
- ::boost::winapi::GetLastError(),
- std::system_category());
- else if (wait_code == ::boost::winapi::wait_timeout)
- return false;
-
- ::boost::winapi::DWORD_ _exit_code;
- if (!::boost::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
- ec = std::error_code(
- ::boost::winapi::GetLastError(),
- std::system_category());
- else
- ec.clear();
-
- exit_code = static_cast<int>(_exit_code);
- ::boost::winapi::CloseHandle(p.proc_info.hProcess);
- p.proc_info.hProcess = ::boost::winapi::INVALID_HANDLE_VALUE_;
- return true;
-;
+ return wait_until(p, exit_code, std::chrono::steady_clock::now() + rel_time, ec);
}
+template< class Rep, class Period >
+inline bool wait_for(
+ child_handle &p,
+ int & exit_code,
+ const std::chrono::duration<Rep, Period>& rel_time)
+{
+ std::error_code ec;
+ bool b = wait_for(p, exit_code, rel_time, ec);
+ boost::process::detail::throw_error(ec, "wait_for error");
+ return b;
+}
}}}}
diff --git a/boost/process/detail/windows/wait_group.hpp b/boost/process/detail/windows/wait_group.hpp
index e0b18b1268..32a8cd8842 100644
--- a/boost/process/detail/windows/wait_group.hpp
+++ b/boost/process/detail/windows/wait_group.hpp
@@ -9,20 +9,12 @@
#include <boost/process/detail/config.hpp>
#include <boost/winapi/jobs.hpp>
#include <boost/winapi/wait.hpp>
-
+#include <chrono>
namespace boost { namespace process { namespace detail { namespace windows {
struct group_handle;
-inline void wait(const group_handle &p)
-{
- if (::boost::winapi::WaitForSingleObject(p.handle(),
- ::boost::winapi::infinite) == ::boost::winapi::wait_failed)
- throw_last_error("WaitForSingleObject() failed");
-
-}
-
inline void wait(const group_handle &p, std::error_code &ec)
{
if (::boost::winapi::WaitForSingleObject(p.handle(),
@@ -30,38 +22,26 @@ inline void wait(const group_handle &p, std::error_code &ec)
ec = get_last_error();
}
-
-template< class Rep, class Period >
-inline bool wait_for(
- const group_handle &p,
- const std::chrono::duration<Rep, Period>& rel_time)
+inline void wait(const group_handle &p)
{
-
- std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(rel_time);
-
- ::boost::winapi::DWORD_ wait_code;
- wait_code = ::boost::winapi::WaitForSingleObject(p.handle(), ms.count());
- if (wait_code == ::boost::winapi::wait_failed)
- throw_last_error("WaitForSingleObject() failed");
- else if (wait_code == ::boost::winapi::wait_timeout)
- return false; //
-
- return true;
+ std::error_code ec;
+ wait(p, ec);
+ boost::process::detail::throw_error(ec, "wait error");
}
-
-template< class Rep, class Period >
-inline bool wait_for(
+template< class Clock, class Duration >
+inline bool wait_until(
const group_handle &p,
- const std::chrono::duration<Rep, Period>& rel_time,
+ const std::chrono::time_point<Clock, Duration>& timeout_time,
std::error_code &ec)
{
-
- std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(rel_time);
-
+ std::chrono::milliseconds ms =
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ timeout_time - Clock::now());
::boost::winapi::DWORD_ wait_code;
wait_code = ::boost::winapi::WaitForSingleObject(p.handle(), ms.count());
+
if (wait_code == ::boost::winapi::wait_failed)
ec = get_last_error();
@@ -76,44 +56,30 @@ inline bool wait_until(
const group_handle &p,
const std::chrono::time_point<Clock, Duration>& timeout_time)
{
- std::chrono::milliseconds ms =
- std::chrono::duration_cast<std::chrono::milliseconds>(
- timeout_time - std::chrono::system_clock::now());
-
- ::boost::winapi::DWORD_ wait_code;
- wait_code = ::boost::winapi::WaitForSingleObject(p.handle(), ms.count());
-
- if (wait_code == ::boost::winapi::wait_failed)
- throw_last_error("WaitForSingleObject() failed");
-
- else if (wait_code == ::boost::winapi::wait_timeout)
- return false; //
-
- return true;
+ std::error_code ec;
+ bool b = wait_until(p, timeout_time, ec);
+ boost::process::detail::throw_error(ec, "wait_until error");
+ return b;
}
-
-template< class Clock, class Duration >
-inline bool wait_until(
+template< class Rep, class Period >
+inline bool wait_for(
const group_handle &p,
- const std::chrono::time_point<Clock, Duration>& timeout_time,
+ const std::chrono::duration<Rep, Period>& rel_time,
std::error_code &ec)
{
- std::chrono::milliseconds ms =
- std::chrono::duration_cast<std::chrono::milliseconds>(
- timeout_time - std::chrono::system_clock::now());
-
- ::boost::winapi::DWORD_ wait_code;
- wait_code = ::boost::winapi::WaitForSingleObject(p.handle(), ms.count());
-
- if (wait_code == ::boost::winapi::wait_failed)
- ec = get_last_error();
-
- else if (wait_code == ::boost::winapi::wait_timeout)
- return false; //
+ return wait_until(p, std::chrono::steady_clock::now() + rel_time, ec);
+}
- return true;
-;
+template< class Rep, class Period >
+inline bool wait_for(
+ const group_handle &p,
+ const std::chrono::duration<Rep, Period>& rel_time)
+{
+ std::error_code ec;
+ bool b = wait_for(p, rel_time, ec);
+ boost::process::detail::throw_error(ec, "wait_for error");
+ return b;
}
}}}}