summaryrefslogtreecommitdiff
path: root/boost/process
diff options
context:
space:
mode:
Diffstat (limited to 'boost/process')
-rw-r--r--boost/process/async.hpp4
-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
-rw-r--r--boost/process/environment.hpp9
-rw-r--r--boost/process/windows.hpp5
27 files changed, 351 insertions, 608 deletions
diff --git a/boost/process/async.hpp b/boost/process/async.hpp
index 4bfe5d4136..a7c2af75b6 100644
--- a/boost/process/async.hpp
+++ b/boost/process/async.hpp
@@ -118,7 +118,9 @@ chlid c2("ls", on_exit=exit_code);
\note The handler is not invoked when the launch fails.
\warning When used \ref ignore_error it might get invoked on error.
-\warning All `on_exit` use one signal(SIGCHLD) on posix, which is only guaranteed to work when all use the same `io_context`.
+\warning `on_exit` uses `boost::asio::signal_set` to listen for `SIGCHLD` on posix, and so has the
+same restrictions as that class (do not register a handler for `SIGCHLD` except by using
+`boost::asio::signal_set`).
*/
constexpr static ::boost::process::detail::on_exit_ on_exit{};
#endif
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;
}
}}}}
diff --git a/boost/process/environment.hpp b/boost/process/environment.hpp
index d8b70fefb8..2729881735 100644
--- a/boost/process/environment.hpp
+++ b/boost/process/environment.hpp
@@ -631,14 +631,17 @@ public:
};
-
+#if !defined(BOOST_NO_ANSI_APIS)
///Definition of the environment for the current process.
typedef basic_native_environment<char> native_environment;
+#endif
///Definition of the environment for the current process.
typedef basic_native_environment<wchar_t> wnative_environment;
+#if !defined(BOOST_NO_ANSI_APIS)
///Type definition to hold a seperate environment.
typedef basic_environment<char> environment;
+#endif
///Type definition to hold a seperate environment.
typedef basic_environment<wchar_t> wenvironment;
@@ -651,8 +654,10 @@ namespace this_process
///Definition of the native handle type.
typedef ::boost::process::detail::api::native_handle_t native_handle_type;
+#if !defined(BOOST_NO_ANSI_APIS)
///Definition of the environment for this process.
using ::boost::process::native_environment;
+#endif
///Definition of the environment for this process.
using ::boost::process::wnative_environment;
@@ -660,8 +665,10 @@ using ::boost::process::wnative_environment;
inline int get_id() { return ::boost::process::detail::api::get_id();}
///Get the native handle of the current process.
inline native_handle_type native_handle() { return ::boost::process::detail::api::native_handle();}
+#if !defined(BOOST_NO_ANSI_APIS)
///Get the enviroment of the current process.
inline native_environment environment() { return ::boost::process:: native_environment(); }
+#endif
///Get the enviroment of the current process.
inline wnative_environment wenvironment() { return ::boost::process::wnative_environment(); }
///Get the path environment variable of the current process runs.
diff --git a/boost/process/windows.hpp b/boost/process/windows.hpp
index 6e740f958f..b1b0f3ef60 100644
--- a/boost/process/windows.hpp
+++ b/boost/process/windows.hpp
@@ -23,6 +23,7 @@ namespace boost {
<emphasis>unspecified</emphasis> <globalname alt="boost::process::windows::not_active">not_active</globalname>;
<emphasis>unspecified</emphasis> <globalname alt="boost::process::windows::show">show</globalname>;
<emphasis>unspecified</emphasis> <globalname alt="boost::process::windows::show_normal">show_normal</globalname>;
+ <emphasis>unspecified</emphasis> <globalname alt="boost::process::windows::create_no_window">create_no_window</globalname>;
}
}
}
@@ -34,7 +35,7 @@ namespace boost {
namespace boost { namespace process {
-///Namespace containing the windows exensions.
+///Namespace containing the windows extensions.
namespace windows {
///Hides the window and activates another window.
@@ -52,6 +53,8 @@ constexpr ::boost::process::detail::windows::show_window<::boost::winapi::SW_SHO
///Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time.
constexpr ::boost::process::detail::windows::show_window<::boost::winapi::SW_SHOWNORMAL_ > show_normal;
+///Adds the [CREATE_NO_WINDOW](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx) flag.
+constexpr ::boost::process::detail::windows::create_no_window_ create_no_window;
}}}