diff options
Diffstat (limited to 'boost/process/detail/posix/wait_for_exit.hpp')
-rw-r--r-- | boost/process/detail/posix/wait_for_exit.hpp | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/boost/process/detail/posix/wait_for_exit.hpp b/boost/process/detail/posix/wait_for_exit.hpp new file mode 100644 index 0000000000..bf25e2a3d8 --- /dev/null +++ b/boost/process/detail/posix/wait_for_exit.hpp @@ -0,0 +1,205 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_DETAIL_POSIX_WAIT_FOR_EXIT_HPP +#define BOOST_PROCESS_DETAIL_POSIX_WAIT_FOR_EXIT_HPP + +#include <boost/process/detail/config.hpp> +#include <boost/process/detail/posix/child_handle.hpp> +#include <system_error> +#include <sys/types.h> +#include <sys/wait.h> + + +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))); + if (ret == -1) + boost::process::detail::throw_last_error("waitpid(2) failed"); + exit_code = status; +} + +inline void wait(const child_handle &p, int & exit_code, std::error_code &ec) noexcept +{ + pid_t ret; + int status; + + do + { + ret = ::waitpid(p.pid, &status, 0); + } + while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status))); + + if (ret == -1) + ec = boost::process::detail::get_last_error(); + else + { + 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) +{ + + 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.pid, &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))); + + + if (ret == -1) + boost::process::detail::throw_last_error("waitpid(2) failed"); + + exit_code = status; + + return !time_out_occured; +} + + +template< class Rep, class Period > +inline bool wait_for( + const child_handle &p, + int & exit_code, + const std::chrono::duration<Rep, Period>& rel_time, + std::error_code & ec) 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.pid, &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))); + + + if (ret == -1) + ec = boost::process::detail::get_last_error(); + else + { + ec.clear(); + exit_code = status; + } + + return !time_out_occured; +} + + + +template< class Rep, class Period > +inline bool wait_until( + const child_handle &p, + int & exit_code, + const std::chrono::duration<Rep, Period>& time_out) +{ + + pid_t ret; + int status; + + bool time_out_occured = false; + do + { + ret = ::waitpid(p.pid, &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))); + + + if (ret == -1) + boost::process::detail::throw_last_error("waitpid(2) failed"); + + exit_code = status; + + return !time_out_occured; +} + + +template< class Rep, class Period > +inline bool wait_until( + const child_handle &p, + int & exit_code, + const std::chrono::duration<Rep, Period>& time_out, + std::error_code & ec) noexcept +{ + + pid_t ret; + int status; + + bool time_out_occured = false; + do + { + ret = ::waitpid(p.pid, &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))); + + + if (ret == -1) + ec = boost::process::detail::get_last_error(); + else + { + ec.clear(); + exit_code = status; + } + + return !time_out_occured; +} + +}}}} + +#endif |