diff options
Diffstat (limited to 'boost/process/detail/posix/wait_group.hpp')
-rw-r--r-- | boost/process/detail/posix/wait_group.hpp | 164 |
1 files changed, 39 insertions, 125 deletions
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; } }}}} |