summaryrefslogtreecommitdiff
path: root/boost/process/detail/posix
diff options
context:
space:
mode:
Diffstat (limited to 'boost/process/detail/posix')
-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
12 files changed, 163 insertions, 336 deletions
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;
}
}}}}