update boost on linux

This commit is contained in:
Bassem Girgis
2019-08-10 16:06:25 -05:00
parent 76ad52be58
commit 861b918727
5363 changed files with 483306 additions and 116507 deletions

View File

@@ -7,7 +7,7 @@
The header which provides the basic asynchrounous features.
It provides the on_exit property, which allows callbacks when the process exits.
It also implements the necessary traits for passing an boost::asio::io_service,
It also implements the necessary traits for passing an boost::asio::io_context,
which is needed for asynchronous communication.
It also pulls the [boost::asio::buffer](http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/buffer.html)
@@ -32,20 +32,20 @@ namespace boost {
#include <boost/process/detail/traits.hpp>
#include <boost/process/detail/on_exit.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/streambuf.hpp>
#include <boost/asio/buffer.hpp>
#include <type_traits>
#include <boost/fusion/iterator/deref.hpp>
#if defined(BOOST_POSIX_API)
#include <boost/process/detail/posix/io_service_ref.hpp>
#include <boost/process/detail/posix/io_context_ref.hpp>
#include <boost/process/detail/posix/async_in.hpp>
#include <boost/process/detail/posix/async_out.hpp>
#include <boost/process/detail/posix/on_exit.hpp>
#elif defined(BOOST_WINDOWS_API)
#include <boost/process/detail/windows/io_service_ref.hpp>
#include <boost/process/detail/windows/io_context_ref.hpp>
#include <boost/process/detail/windows/async_in.hpp>
#include <boost/process/detail/windows/async_out.hpp>
#include <boost/process/detail/windows/on_exit.hpp>
@@ -56,25 +56,25 @@ namespace boost { namespace process { namespace detail {
struct async_tag;
template<typename T>
struct is_io_service : std::false_type {};
struct is_io_context : std::false_type {};
template<>
struct is_io_service<api::io_service_ref> : std::true_type {};
struct is_io_context<api::io_context_ref> : std::true_type {};
template<typename Tuple>
inline asio::io_service& get_io_service(const Tuple & tup)
inline asio::io_context& get_io_context(const Tuple & tup)
{
auto& ref = *boost::fusion::find_if<is_io_service<boost::mpl::_>>(tup);
auto& ref = *boost::fusion::find_if<is_io_context<boost::mpl::_>>(tup);
return ref.get();
}
struct async_builder
{
boost::asio::io_service * ios;
boost::asio::io_context * ios;
void operator()(boost::asio::io_service & ios_) {this->ios = &ios_;};
void operator()(boost::asio::io_context & ios_) {this->ios = &ios_;};
typedef api::io_service_ref result_type;
api::io_service_ref get_initializer() {return api::io_service_ref (*ios);};
typedef api::io_context_ref result_type;
api::io_context_ref get_initializer() {return api::io_context_ref (*ios);};
};
@@ -90,7 +90,7 @@ using ::boost::asio::buffer;
#if defined(BOOST_PROCESS_DOXYGEN)
/** When an io_service is passed, the on_exit property can be used, to be notified
/** When an io_context is passed, the on_exit property can be used, to be notified
when the child process exits.
@@ -107,7 +107,7 @@ with `function` being a callable object with the signature `(int, const std::err
\par Example
\code{.cpp}
io_service ios;
io_context ios;
child c("ls", on_exit=[](int exit, const std::error_code& ec_in){});
@@ -117,8 +117,10 @@ chlid c2("ls", on_exit=exit_code);
\endcode
\note The handler is not invoked when the launch fails.
\warning When used \ref ignore_error it might gte invoked on error.
\warning When used \ref ignore_error it might get invoked on error.
\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

View File

@@ -48,31 +48,31 @@ public:
typedef platform_specific handle_type;
/** Construct a new async_pipe, does automatically open the pipe.
* Initializes source and sink with the same io_service.
* Initializes source and sink with the same io_context.
* @note Windows creates a named pipe here, where the name is automatically generated.
*/
inline async_pipe(boost::asio::io_service & ios);
inline async_pipe(boost::asio::io_context & ios);
/** Construct a new async_pipe, does automatically open the pipe.
* @note Windows creates a named pipe here, where the name is automatically generated.
*/
inline async_pipe(boost::asio::io_service & ios_source,
boost::asio::io_service & ios_sink);
inline async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & ios_sink);
/** Construct a new async_pipe, does automatically open.
* Initializes source and sink with the same io_service.
* Initializes source and sink with the same io_context.
*
* @note Windows restricts possible names.
*/
inline async_pipe(boost::asio::io_service & ios, const std::string & name);
inline async_pipe(boost::asio::io_context & ios, const std::string & name);
/** Construct a new async_pipe, does automatically open.
*
* @note Windows restricts possible names.
*/
inline async_pipe(boost::asio::io_service & ios_source,
boost::asio::io_service & ios_sink, const std::string & name);
inline async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & ios_sink, const std::string & name);
/** Copy-Constructor of the async pipe.
* @note Windows requires a named pipe for this, if a the wrong type is used an exception is thrown.
@@ -89,15 +89,15 @@ public:
*
*/
template<class CharT, class Traits = std::char_traits<CharT>>
explicit async_pipe(boost::asio::io_service & ios, const basic_pipe<CharT, Traits> & p);
explicit async_pipe(boost::asio::io_context & ios, const basic_pipe<CharT, Traits> & p);
/** Construct the async-pipe from a pipe, with two different io_service objects.
/** Construct the async-pipe from a pipe, with two different io_context objects.
* @note Windows requires a named pipe for this, if a the wrong type is used an exception is thrown.
*
*/
template<class CharT, class Traits = std::char_traits<CharT>>
explicit async_pipe(boost::asio::io_service & ios_source,
boost::asio::io_service & ios_sink,
explicit async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & ios_sink,
const basic_pipe<CharT, Traits> & p);
@@ -189,15 +189,15 @@ public:
///Get the asio handle of the pipe source. Qualified as rvalue
handle_type && source() &&;
/// Move the source out of this class and change the io_service. Qualified as rvalue. \attention Will always move.
handle_type source(::boost::asio::io_service& ios) &&;
/// Move the sink out of this class and change the io_service. Qualified as rvalue. \attention Will always move
handle_type sink (::boost::asio::io_service& ios) &&;
/// Move the source out of this class and change the io_context. Qualified as rvalue. \attention Will always move.
handle_type source(::boost::asio::io_context& ios) &&;
/// Move the sink out of this class and change the io_context. Qualified as rvalue. \attention Will always move
handle_type sink (::boost::asio::io_context& ios) &&;
/// Copy the source out of this class and change the io_service. \attention Will always copy.
handle_type source(::boost::asio::io_service& ios) const &;
/// Copy the sink out of this class and change the io_service. \attention Will always copy
handle_type sink (::boost::asio::io_service& ios) const &;
/// Copy the source out of this class and change the io_context. \attention Will always copy.
handle_type source(::boost::asio::io_context& ios) const &;
/// Copy the sink out of this class and change the io_context. \attention Will always copy
handle_type sink (::boost::asio::io_context& ios) const &;

View File

@@ -25,6 +25,7 @@
#include <type_traits>
#include <memory>
#include <boost/asio/async_result.hpp>
#include <boost/asio/post.hpp>
#include <boost/system/error_code.hpp>
#include <tuple>
@@ -40,8 +41,8 @@ namespace detail
template<typename ExitHandler>
struct async_system_handler : ::boost::process::detail::api::async_handler
{
boost::asio::io_service & ios;
boost::asio::detail::async_result_init<
boost::asio::io_context & ios;
boost::asio::async_completion<
ExitHandler, void(boost::system::error_code, int)> init;
#if defined(BOOST_POSIX_API)
@@ -50,8 +51,8 @@ struct async_system_handler : ::boost::process::detail::api::async_handler
template<typename ExitHandler_>
async_system_handler(
boost::asio::io_service & ios,
ExitHandler_ && exit_handler) : ios(ios), init(std::forward<ExitHandler_>(exit_handler))
boost::asio::io_context & ios,
ExitHandler_ && exit_handler) : ios(ios), init(exit_handler)
{
}
@@ -63,12 +64,13 @@ struct async_system_handler : ::boost::process::detail::api::async_handler
#if defined(BOOST_POSIX_API)
errored = true;
#endif
auto & h = init.handler;
ios.post(
[h, ec]() mutable
{
h(boost::system::error_code(ec.value(), boost::system::system_category()), -1);
});
auto & h = init.completion_handler;
boost::asio::post(
ios.get_executor(),
[h, ec]() mutable
{
h(boost::system::error_code(ec.value(), boost::system::system_category()), -1);
});
}
BOOST_ASIO_INITFN_RESULT_TYPE(ExitHandler, void (boost::system::error_code, int))
@@ -82,9 +84,9 @@ struct async_system_handler : ::boost::process::detail::api::async_handler
{
#if defined(BOOST_POSIX_API)
if (errored)
return [](int exit_code, const std::error_code & ec){};
return [](int , const std::error_code &){};
#endif
auto & h = init.handler;
auto & h = init.completion_handler;
return [h](int exit_code, const std::error_code & ec) mutable
{
h(boost::system::error_code(ec.value(), boost::system::system_category()), exit_code);
@@ -106,7 +108,7 @@ but is similar to the asynchronous functions in [boost.asio](http://www.boost.or
It uses [asio::async_result](http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/async_result.html) to determine
the return value (from the second parameter, `exit_handler`).
\param ios A reference to an [io_service](http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference.html)
\param ios A reference to an [io_context](http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference.html)
\param exit_handler The exit-handler for the signature `void(boost::system::error_code, int)`
\note This function does not allow custom error handling, since those are done through the `exit_handler`.
@@ -115,12 +117,12 @@ the return value (from the second parameter, `exit_handler`).
#if defined(BOOST_PROCESS_DOXYGEN)
template<typename ExitHandler, typename ...Args>
inline boost::process::detail::dummy
async_system(boost::asio::io_service & ios, ExitHandler && exit_handler, Args && ...args);
async_system(boost::asio::io_context & ios, ExitHandler && exit_handler, Args && ...args);
#endif
template<typename ExitHandler, typename ...Args>
inline BOOST_ASIO_INITFN_RESULT_TYPE(ExitHandler, void (boost::system::error_code, int))
async_system(boost::asio::io_service & ios, ExitHandler && exit_handler, Args && ...args)
async_system(boost::asio::io_context & ios, ExitHandler && exit_handler, Args && ...args)
{
detail::async_system_handler<ExitHandler> async_h{ios, std::forward<ExitHandler>(exit_handler)};

View File

@@ -35,6 +35,9 @@ child::child(Args&&...args)
: child(::boost::process::detail::execute_impl(std::forward<Args>(args)...)) {}
///Typedef for the type of an pid_t
typedef ::boost::process::detail::api::pid_t pid_t;
#if defined(BOOST_PROCESS_DOXYGEN)
/** The main class to hold a child process. It is simliar to [std::thread](http://en.cppreference.com/w/cpp/thread/thread),
* in that it has a join and detach function.
@@ -89,6 +92,10 @@ class child
/** Get the Process Identifier. */
pid_t id() const;
/** Get the native, uninterpreted exit code. The return value is without any meaning if the child wasn't waited
* for or if it was terminated. */
int native_exit_code() const;
/** Check if the child process is running. */
bool running();
/** \overload void running() */

View File

@@ -11,7 +11,7 @@
#ifndef BOOST_PROCESS_DETAIL_CMD_LINE_HPP
#define BOOST_PROCESS_DETAIL_CMD_LINE_HPP
#include <boost/detail/winapi/config.hpp>
#include <boost/winapi/config.hpp>
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/traits/cmd_or_exe.hpp>

View File

@@ -27,37 +27,37 @@ namespace detail {
#if defined(BOOST_POSIX_API)
using ::boost::process::detail::posix::is_async_handler;
using ::boost::process::detail::posix::does_require_io_service;
using ::boost::process::detail::posix::does_require_io_context;
#else
using ::boost::process::detail::windows::is_async_handler;
using ::boost::process::detail::windows::does_require_io_service;
using ::boost::process::detail::windows::does_require_io_context;
#endif
template<typename ...Args>
struct has_io_service;
struct has_io_context;
template<typename T, typename ...Args>
struct has_io_service<T, Args...>
struct has_io_context<T, Args...>
{
typedef typename has_io_service<Args...>::type next;
typedef typename has_io_context<Args...>::type next;
typedef typename std::is_same<
typename std::remove_reference<T>::type,
boost::asio::io_service>::type is_ios;
boost::asio::io_context>::type is_ios;
typedef typename std::conditional<is_ios::value,
std::true_type,
next>::type type;
};
template<typename T>
struct has_io_service<T>
struct has_io_context<T>
{
typedef typename std::is_same<
typename std::remove_reference<T>::type,
boost::asio::io_service>::type type;
boost::asio::io_context>::type type;
};
template<typename ...Args>
using has_io_service_t = typename has_io_service<Args...>::type;
using has_io_context_t = typename has_io_context<Args...>::type;
template<typename ...Args>
struct has_async_handler;
@@ -79,34 +79,34 @@ struct has_async_handler<T>
};
template<typename ...Args>
struct needs_io_service;
struct needs_io_context;
template<typename T, typename ...Args>
struct needs_io_service<T, Args...>
struct needs_io_context<T, Args...>
{
typedef typename needs_io_service<Args...>::type next;
typedef typename does_require_io_service<T>::type is_ios;
typedef typename needs_io_context<Args...>::type next;
typedef typename does_require_io_context<T>::type is_ios;
typedef typename std::conditional<is_ios::value,
std::true_type,
next>::type type;
};
template<typename T>
struct needs_io_service<T>
struct needs_io_context<T>
{
typedef typename does_require_io_service<T>::type type;
typedef typename does_require_io_context<T>::type type;
};
template<typename ...Args>
boost::asio::io_service &get_io_service_var(boost::asio::io_service & f, Args&...)
boost::asio::io_context &get_io_context_var(boost::asio::io_context & f, Args&...)
{
return f;
}
template<typename First, typename ...Args>
boost::asio::io_service &get_io_service_var(First&, Args&...args)
boost::asio::io_context &get_io_context_var(First&, Args&...args)
{
return get_io_service_var(args...);
return get_io_context_var(args...);
}
}

View File

@@ -65,7 +65,8 @@ public:
child(child && lhs) noexcept
: _child_handle(std::move(lhs._child_handle)),
_exit_status(std::move(lhs._exit_status)),
_attached (lhs._attached)
_attached (lhs._attached),
_terminated (lhs._terminated)
{
lhs._attached = false;
}
@@ -79,6 +80,7 @@ public:
_child_handle= std::move(lhs._child_handle);
_exit_status = std::move(lhs._exit_status);
_attached = lhs._attached;
_terminated = lhs._terminated;
lhs._attached = false;
return *this;
};
@@ -99,74 +101,56 @@ public:
int exit_code() const {return ::boost::process::detail::api::eval_exit_status(_exit_status->load());}
pid_t id() const {return _child_handle.id(); }
int native_exit_code() const {return _exit_status->load();}
bool running()
{
if (valid() && !_exited())
{
int code;
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;
}
@@ -192,17 +176,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 >

View File

@@ -31,7 +31,7 @@
extern char **environ;
#endif
#elif defined(BOOST_WINDOWS_API)
#include <boost/detail/winapi/get_last_error.hpp>
#include <boost/winapi/get_last_error.hpp>
#else
#error "System API not supported by boost.process"
#endif
@@ -53,17 +53,21 @@ inline std::error_code get_last_error() noexcept
}
//copied from linux spec.
#if defined (__USE_XOPEN_EXTENDED) && !defined (__USE_XOPEN2K8) || defined( __USE_BSD)
#if (_XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
#define BOOST_POSIX_HAS_VFORK 1
#endif
#if (_POSIX_C_SOURCE >= 199309L)
#define BOOST_POSIX_HAS_SIGTIMEDWAIT 1
#endif
#elif defined(BOOST_WINDOWS_API)
namespace windows {namespace extensions {}}
namespace api = windows;
inline std::error_code get_last_error() noexcept
{
return std::error_code(::boost::detail::winapi::GetLastError(), std::system_category());
return std::error_code(::boost::winapi::GetLastError(), std::system_category());
}
#endif
@@ -72,11 +76,27 @@ inline void throw_last_error(const std::string & msg)
throw process_error(get_last_error(), msg);
}
inline void throw_last_error(const char * msg)
{
throw process_error(get_last_error(), msg);
}
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';}

View File

@@ -20,34 +20,39 @@ template<typename Allocator>
class basic_streambuf;
typedef basic_streambuf<std::allocator<char>> streambuf;
class io_service;
class io_context;
class executor;
#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
class signal_set_service;
template <typename SignalSetService>
class basic_signal_set;
typedef basic_signal_set<signal_set_service> signal_set;
#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
template <typename Executor>
class basic_signal_set;
typedef basic_signal_set<executor> signal_set;
#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
template <typename Handler>
class basic_yield_context;
namespace posix {
#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
class stream_descriptor_service;
template <typename StreamDesscriptorService>
class basic_stream_descriptor;
typedef basic_stream_descriptor<stream_descriptor_service> stream_descriptor;
class object_handle_service;
template <typename ObjectHandleService>
class basic_object_handle;
typedef basic_object_handle<object_handle_service> object_handle;
#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
template <typename Executor>
class basic_stream_descriptor;
typedef basic_stream_descriptor<executor> stream_descriptor;
#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
} //posix
} //asio

View File

@@ -12,9 +12,9 @@
namespace boost { namespace process { namespace detail { namespace posix {
struct require_io_service {};
struct require_io_context {};
struct async_handler : handler_base_ext, require_io_service
struct async_handler : handler_base_ext, require_io_context
{
};
@@ -26,13 +26,13 @@ template<typename T>
struct is_async_handler<const T&> : std::is_base_of<async_handler, T> {};
template<typename T>
struct does_require_io_service : std::is_base_of<require_io_service, T> {};
struct does_require_io_context : std::is_base_of<require_io_context, T> {};
template<typename T>
struct does_require_io_service<T&> : std::is_base_of<require_io_service, T> {};
struct does_require_io_context<T&> : std::is_base_of<require_io_context, T> {};
template<typename T>
struct does_require_io_service<const T&> : std::is_base_of<require_io_service, T> {};
struct does_require_io_context<const T&> : std::is_base_of<require_io_context, T> {};
}}}}

View File

@@ -22,7 +22,7 @@ namespace boost { namespace process { namespace detail { namespace posix {
template<typename Buffer>
struct async_in_buffer : ::boost::process::detail::posix::handler_base_ext,
::boost::process::detail::posix::require_io_service
::boost::process::detail::posix::require_io_context
{
Buffer & buf;
@@ -39,30 +39,30 @@ struct async_in_buffer : ::boost::process::detail::posix::handler_base_ext,
{
}
template <typename Executor>
inline void on_success(Executor &exec)
inline void on_success(Executor)
{
auto pipe = this->pipe;
auto pipe_ = this->pipe;
if (this->promise)
{
auto promise = this->promise;
auto promise_ = this->promise;
boost::asio::async_write(*pipe, buf,
[pipe, promise](const boost::system::error_code & ec, std::size_t)
boost::asio::async_write(*pipe_, buf,
[pipe_, promise_](const boost::system::error_code & ec, std::size_t)
{
if (ec && (ec.value() != EBADF) && (ec.value() != EPERM) && (ec.value() != ENOENT))
{
std::error_code e(ec.value(), std::system_category());
promise->set_exception(std::make_exception_ptr(process_error(e)));
promise_->set_exception(std::make_exception_ptr(process_error(e)));
}
else
promise->set_value();
promise_->set_value();
});
}
else
boost::asio::async_write(*pipe, buf,
[pipe](const boost::system::error_code&ec, std::size_t size){});
boost::asio::async_write(*pipe_, buf,
[pipe_](const boost::system::error_code&, std::size_t){});
std::move(*pipe).source().close();
std::move(*pipe_).source().close();
this->pipe = nullptr;
}
@@ -76,7 +76,7 @@ struct async_in_buffer : ::boost::process::detail::posix::handler_base_ext,
template<typename Executor>
void on_setup(Executor & exec)
{
pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq));
}
template <typename Executor>
@@ -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());
}
};

View File

@@ -45,7 +45,7 @@ inline int apply_out_handles(int handle, std::integral_constant<int, 1>, std::in
template<int p1, int p2, typename Buffer>
struct async_out_buffer : ::boost::process::detail::posix::handler_base_ext,
::boost::process::detail::posix::require_io_service
::boost::process::detail::posix::require_io_context
{
Buffer & buf;
@@ -61,7 +61,7 @@ struct async_out_buffer : ::boost::process::detail::posix::handler_base_ext,
{
auto pipe = this->pipe;
boost::asio::async_read(*pipe, buf,
[pipe](const boost::system::error_code&, std::size_t size){});
[pipe](const boost::system::error_code&, std::size_t){});
this->pipe = nullptr;
std::move(*pipe).sink().close();
@@ -76,7 +76,7 @@ struct async_out_buffer : ::boost::process::detail::posix::handler_base_ext,
template<typename Executor>
void on_setup(Executor & exec)
{
pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq));
}
@@ -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());
}
};
@@ -97,7 +99,7 @@ struct async_out_buffer : ::boost::process::detail::posix::handler_base_ext,
template<int p1, int p2, typename Type>
struct async_out_future : ::boost::process::detail::posix::handler_base_ext,
::boost::process::detail::posix::require_io_service
::boost::process::detail::posix::require_io_context
{
std::shared_ptr<std::promise<Type>> promise = std::make_shared<std::promise<Type>>();
@@ -110,32 +112,32 @@ struct async_out_future : ::boost::process::detail::posix::handler_base_ext,
fut = promise->get_future();
}
template <typename Executor>
inline void on_success(Executor &exec)
inline void on_success(Executor &)
{
auto pipe = this->pipe;
auto pipe_ = this->pipe;
auto buffer = this->buffer;
auto promise = this->promise;
auto buffer_ = this->buffer;
auto promise_ = this->promise;
boost::asio::async_read(*pipe, *buffer,
[pipe, buffer, promise](const boost::system::error_code& ec, std::size_t size)
boost::asio::async_read(*pipe_, *buffer_,
[pipe_, buffer_, promise_](const boost::system::error_code& ec, std::size_t)
{
if (ec && (ec.value() != ENOENT))
{
std::error_code e(ec.value(), std::system_category());
promise->set_exception(std::make_exception_ptr(process_error(e)));
promise_->set_exception(std::make_exception_ptr(process_error(e)));
}
else
{
std::istream is (buffer.get());
std::istream is (buffer_.get());
Type arg;
arg.resize(buffer->size());
is.read(&*arg.begin(), buffer->size());
promise->set_value(std::move(arg));
arg.resize(buffer_->size());
is.read(&*arg.begin(), buffer_->size());
promise_->set_value(std::move(arg));
}
});
std::move(*pipe).sink().close();
std::move(*pipe_).sink().close();
this->pipe = nullptr;
}
@@ -148,7 +150,7 @@ struct async_out_future : ::boost::process::detail::posix::handler_base_ext,
template<typename Executor>
void on_setup(Executor & exec)
{
pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq));
}
template <typename Executor>
@@ -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());
}
};

View File

@@ -9,8 +9,10 @@
#include <boost/process/detail/posix/basic_pipe.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>
#include <boost/asio/post.hpp>
#include <system_error>
#include <string>
#include <utility>
namespace boost { namespace process { namespace detail { namespace posix {
@@ -22,10 +24,10 @@ public:
typedef int native_handle_type;
typedef ::boost::asio::posix::stream_descriptor handle_type;
inline async_pipe(boost::asio::io_service & ios) : async_pipe(ios, ios) {}
inline async_pipe(boost::asio::io_context & ios) : async_pipe(ios, ios) {}
inline async_pipe(boost::asio::io_service & ios_source,
boost::asio::io_service & ios_sink) : _source(ios_source), _sink(ios_sink)
inline async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & ios_sink) : _source(ios_source), _sink(ios_sink)
{
int fds[2];
if (::pipe(fds) == -1)
@@ -34,11 +36,11 @@ public:
_source.assign(fds[0]);
_sink .assign(fds[1]);
};
inline async_pipe(boost::asio::io_service & ios, const std::string & name)
inline async_pipe(boost::asio::io_context & ios, const std::string & name)
: async_pipe(ios, ios, name) {}
inline async_pipe(boost::asio::io_service & ios_source,
boost::asio::io_service & io_sink, const std::string & name);
inline async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & io_sink, const std::string & name);
inline async_pipe(const async_pipe& lhs);
async_pipe(async_pipe&& lhs) : _source(std::move(lhs._source)), _sink(std::move(lhs._sink))
{
@@ -47,15 +49,15 @@ public:
}
template<class CharT, class Traits = std::char_traits<CharT>>
explicit async_pipe(::boost::asio::io_service & ios_source,
::boost::asio::io_service & ios_sink,
explicit async_pipe(::boost::asio::io_context & ios_source,
::boost::asio::io_context & ios_sink,
const basic_pipe<CharT, Traits> & p)
: _source(ios_source, p.native_source()), _sink(ios_sink, p.native_sink())
{
}
template<class CharT, class Traits = std::char_traits<CharT>>
explicit async_pipe(boost::asio::io_service & ios, const basic_pipe<CharT, Traits> & p)
explicit async_pipe(boost::asio::io_context & ios, const basic_pipe<CharT, Traits> & p)
: async_pipe(ios, ios, p)
{
}
@@ -68,10 +70,10 @@ public:
~async_pipe()
{
if (_sink .native() != -1)
::close(_sink.native());
if (_source.native() != -1)
::close(_source.native());
if (_sink .native_handle() != -1)
::close(_sink.native_handle());
if (_source.native_handle() != -1)
::close(_source.native_handle());
}
template<class CharT, class Traits = std::char_traits<CharT>>
@@ -108,9 +110,9 @@ public:
void async_close()
{
if (_sink.is_open())
_sink.get_io_service(). post([this]{_sink.close();});
boost::asio::post(_sink.get_executor(), [this]{_sink.close();});
if (_source.is_open())
_source.get_io_service().post([this]{_source.close();});
boost::asio::post(_source.get_executor(), [this]{_source.close();});
}
template<typename MutableBufferSequence>
@@ -124,8 +126,20 @@ public:
return _sink.write_some(buffers);
}
native_handle_type native_source() const {return const_cast<boost::asio::posix::stream_descriptor&>(_source).native();}
native_handle_type native_sink () const {return const_cast<boost::asio::posix::stream_descriptor&>(_sink ).native();}
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();}
template<typename MutableBufferSequence,
typename ReadHandler>
@@ -135,7 +149,7 @@ public:
const MutableBufferSequence & buffers,
ReadHandler &&handler)
{
_source.async_read_some(buffers, std::forward<ReadHandler>(handler));
return _source.async_read_some(buffers, std::forward<ReadHandler>(handler));
}
template<typename ConstBufferSequence,
@@ -146,7 +160,7 @@ public:
const ConstBufferSequence & buffers,
WriteHandler&& handler)
{
_sink.async_write_some(buffers, std::forward<WriteHandler>(handler));
return _sink.async_write_some(buffers, std::forward<WriteHandler>(handler));
}
@@ -156,32 +170,32 @@ public:
handle_type && sink() && { return std::move(_sink); }
handle_type && source()&& { return std::move(_source); }
handle_type source(::boost::asio::io_service& ios) &&
handle_type source(::boost::asio::io_context& ios) &&
{
::boost::asio::posix::stream_descriptor stolen(ios, _source.release());
return stolen;
}
handle_type sink (::boost::asio::io_service& ios) &&
handle_type sink (::boost::asio::io_context& ios) &&
{
::boost::asio::posix::stream_descriptor stolen(ios, _sink.release());
return stolen;
}
handle_type source(::boost::asio::io_service& ios) const &
handle_type source(::boost::asio::io_context& ios) const &
{
auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native();
auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native_handle();
return ::boost::asio::posix::stream_descriptor(ios, ::dup(source_in));
}
handle_type sink (::boost::asio::io_service& ios) const &
handle_type sink (::boost::asio::io_context& ios) const &
{
auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native();
auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native_handle();
return ::boost::asio::posix::stream_descriptor(ios, ::dup(sink_in));
}
};
async_pipe::async_pipe(boost::asio::io_service & ios_source,
boost::asio::io_service & ios_sink,
async_pipe::async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & ios_sink,
const std::string & name) : _source(ios_source), _sink(ios_sink)
{
auto fifo = mkfifo(name.c_str(), 0666 );
@@ -205,19 +219,19 @@ async_pipe::async_pipe(boost::asio::io_service & ios_source,
}
async_pipe::async_pipe(const async_pipe & p) :
_source(const_cast<async_pipe&>(p)._source.get_io_service()),
_sink( const_cast<async_pipe&>(p)._sink.get_io_service())
_source(const_cast<async_pipe&>(p)._source.get_executor()),
_sink( const_cast<async_pipe&>(p)._sink.get_executor())
{
//cannot get the handle from a const object.
auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native();
auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native();
auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native_handle();
auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native_handle();
if (source_in == -1)
_source.assign(-1);
else
{
_source.assign(::dup(source_in));
if (_source.native()== -1)
if (_source.native_handle()== -1)
::boost::process::detail::throw_last_error("dup()");
}
@@ -226,7 +240,7 @@ async_pipe::async_pipe(const async_pipe & p) :
else
{
_sink.assign(::dup(sink_in));
if (_sink.native() == -1)
if (_sink.native_handle() == -1)
::boost::process::detail::throw_last_error("dup()");
}
}
@@ -237,8 +251,8 @@ async_pipe& async_pipe::operator=(const async_pipe & p)
int sink;
//cannot get the handle from a const object.
auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native();
auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native();
auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(p._source).native_handle();
auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(p._sink).native_handle();
if (source_in == -1)
source = -1;
else
@@ -264,16 +278,8 @@ async_pipe& async_pipe::operator=(const async_pipe & p)
async_pipe& async_pipe::operator=(async_pipe && lhs)
{
if (_source.native_handle() == -1)
::close(_source.native());
if (_sink.native_handle() == -1)
::close(_sink.native());
_source.assign(lhs._source.native_handle());
_sink .assign(lhs._sink .native_handle());
lhs._source.assign(-1);
lhs._sink .assign(-1);
std::swap(_source, lhs._source);
std::swap(_sink, lhs._sink);
return *this;
}
@@ -284,8 +290,8 @@ async_pipe::operator basic_pipe<CharT, Traits>() const
int sink;
//cannot get the handle from a const object.
auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native();
auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native();
auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native_handle();
auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native_handle();
if (source_in == -1)

View File

@@ -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);

View File

@@ -29,7 +29,7 @@ class basic_pipe
int _sink = -1;
public:
explicit basic_pipe(int source, int sink) : _source(source), _sink(sink) {}
explicit basic_pipe(int source, int sink, const std::string & name) : _source(source), _sink(sink) {}
explicit basic_pipe(int source, int sink, const std::string&) : _source(source), _sink(sink) {}
typedef CharT char_type ;
typedef Traits traits_type;
typedef typename Traits::int_type int_type ;
@@ -105,8 +105,10 @@ public:
void close()
{
::close(_source);
::close(_sink);
if (_source != -1)
::close(_source);
if (_sink != -1)
::close(_sink);
_source = -1;
_sink = -1;
}

View File

@@ -44,7 +44,7 @@ struct child_handle
return pid;
}
bool in_group() const {return true;}
bool in_group(std::error_code &ec) const noexcept {return true;}
bool in_group(std::error_code&) const noexcept {return true;}
typedef int process_handle_t;
process_handle_t process_handle() const { return pid; }

View File

@@ -45,7 +45,7 @@ inline int execvpe(const char* filename, char * const arg_list[], char* env[])
if (e != nullptr)
{
std::vector<std::string> path;
std::vector<std::string> path;
boost::split(path, *e, boost::is_any_of(":"));
for (const std::string & pp : path)
@@ -85,7 +85,7 @@ struct on_error_t
template<typename T>
void operator()(T & t) const
{
t.on_error(exec, error);
t.on_error(exec, error);
}
};
@@ -157,13 +157,13 @@ struct on_fork_success_t
};
template<typename Executor> on_setup_t <Executor> call_on_setup (Executor & exec) {return exec;}
template<typename Executor> on_error_t <Executor> call_on_error (Executor & exec, const std::error_code & ec)
template<typename Executor> on_error_t <Executor> call_on_error (Executor & exec, const std::error_code & ec)
{
return on_error_t<Executor> (exec, ec);
}
template<typename Executor> on_success_t<Executor> call_on_success(Executor & exec) {return exec;}
template<typename Executor> on_fork_error_t <Executor> call_on_fork_error (Executor & exec, const std::error_code & ec)
template<typename Executor> on_fork_error_t <Executor> call_on_fork_error (Executor & exec, const std::error_code & ec)
{
return on_fork_error_t<Executor> (exec, ec);
}
@@ -180,7 +180,7 @@ template<typename Sequence>
class executor
{
template<typename HasHandler, typename UseVFork>
void internal_error_handle(const std::error_code &ec, const char* msg, HasHandler, boost::mpl::true_, UseVFork) {}
void internal_error_handle(const std::error_code&, const char*, HasHandler, boost::mpl::true_, UseVFork) {}
int _pipe_sink = -1;
@@ -233,7 +233,8 @@ class executor
void check_error(boost::mpl::true_) {};
void check_error(boost::mpl::false_)
{
throw process_error(_ec, _msg);
if (_ec)
throw process_error(_ec, _msg);
}
typedef typename ::boost::process::detail::has_error_handler<Sequence>::type has_error_handler;
@@ -292,10 +293,14 @@ class executor
auto err = errno;
if ((err == EBADF) || (err == EPERM))//that should occur on success, therefore return.
return;
//EAGAIN not yet forked, EINTR interrupted, i.e. try again
//EAGAIN not yet forked, EINTR interrupted, i.e. try again
else if ((err != EAGAIN ) && (err != EINTR))
{
::close(source);
set_error(std::error_code(err, std::system_category()), "Error read pipe");
}
}
::close(source);
set_error(ec, std::move(msg));
}
@@ -375,7 +380,10 @@ child executor<Sequence>::invoke(boost::mpl::false_, boost::mpl::false_)
}
if (::fcntl(p[1], F_SETFD, FD_CLOEXEC) == -1)
{
set_error(::boost::process::detail::get_last_error(), "fcntl(2) failed");
auto err = ::boost::process::detail::get_last_error();
::close(p[0]);
::close(p[1]);
set_error(err, "fcntl(2) failed");
return child();
}
_ec.clear();
@@ -419,11 +427,8 @@ child executor<Sequence>::invoke(boost::mpl::false_, boost::mpl::false_)
child c(child_handle(pid), exit_status);
::close(p[1]);
_read_error(p[0]);
::close(p[0]);
if (_ec)
{

View File

@@ -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;
@@ -59,26 +56,17 @@ struct group_handle
{
return ::getpgid(proc) == grp;
}
bool has(handle_t proc, std::error_code & ec) noexcept
bool has(handle_t proc, std::error_code &) 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_ */

View File

@@ -28,7 +28,7 @@ struct group_ref : handler_base_ext
{}
template <class Executor>
void on_exec_setup(Executor& exec) const
void on_exec_setup(Executor&) const
{
if (grp.grp == -1)
::setpgid(0, 0);

View File

@@ -3,13 +3,12 @@
// 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_POSIX_IO_SERVICE_REF_HPP_
#define BOOST_PROCESS_POSIX_IO_SERVICE_REF_HPP_
#ifndef BOOST_PROCESS_POSIX_IO_CONTEXT_REF_HPP_
#define BOOST_PROCESS_POSIX_IO_CONTEXT_REF_HPP_
#include <boost/process/detail/posix/handler.hpp>
#include <boost/process/detail/posix/async_handler.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/signal_set.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/algorithm/transformation/filter_if.hpp>
@@ -18,6 +17,9 @@
#include <boost/fusion/container/vector/convert.hpp>
#include <boost/process/detail/posix/sigchld_service.hpp>
#include <boost/process/detail/posix/is_running.hpp>
#include <functional>
#include <type_traits>
#include <memory>
@@ -62,23 +64,22 @@ struct async_handler_collector
void operator()(T & t) const
{
handlers.push_back(t.on_exit_handler(exec));
};
}
};
//Also set's up waiting for the exit, so it can close async stuff.
struct io_service_ref : handler_base_ext
struct io_context_ref : handler_base_ext
{
io_service_ref(boost::asio::io_service & ios) : ios(ios)
io_context_ref(boost::asio::io_context & ios) : ios(ios)
{
}
boost::asio::io_service &get() {return ios;};
boost::asio::signal_set *signal_p = nullptr;
boost::asio::io_context &get() {return ios;};
template <class Executor>
void on_setup(Executor& exec)
void on_success(Executor& exec)
{
ios.notify_fork(boost::asio::io_context::fork_parent);
//must be on the heap so I can move it into the lambda.
auto asyncs = boost::fusion::filter_if<
is_async_handler<
@@ -93,63 +94,32 @@ struct io_service_ref : handler_base_ext
funcs.reserve(boost::fusion::size(asyncs));
boost::fusion::for_each(asyncs, async_handler_collector<Executor>(exec, funcs));
wait_handler wh(std::move(funcs), ios, exec.exit_status);
auto & es = exec.exit_status;
signal_p = wh.signal_.get();
signal_p->async_wait(std::move(wh));
auto wh = [funcs, es](int val, const std::error_code & ec)
{
es->store(val);
for (auto & func : funcs)
func(::boost::process::detail::posix::eval_exit_status(val), ec);
};
sigchld_service.async_wait(exec.pid, std::move(wh));
}
template<typename Executor>
void on_setup (Executor &) const {/*ios.notify_fork(boost::asio::io_context::fork_prepare);*/}
template<typename Executor>
void on_exec_setup (Executor &) const {/*ios.notify_fork(boost::asio::io_context::fork_child);*/}
template <class Executor>
void on_error(Executor & exec, const std::error_code & ec) const
{
if (signal_p != nullptr)
{
boost::system::error_code ec;
signal_p->cancel(ec);
}
}
void on_error(Executor&, const std::error_code &) const {/*ios.notify_fork(boost::asio::io_context::fork_parent);*/}
struct wait_handler
{
std::shared_ptr<boost::asio::signal_set> signal_;
std::vector<std::function<void(int, const std::error_code & ec)>> funcs;
std::shared_ptr<std::atomic<int>> exit_status;
wait_handler(const wait_handler & ) = default;
wait_handler(wait_handler && ) = default;
wait_handler(
std::vector<std::function<void(int, const std::error_code & ec)>> && funcs,
boost::asio::io_service & ios,
const std::shared_ptr<std::atomic<int>> &exit_status)
: signal_(new boost::asio::signal_set(ios, SIGCHLD)),
funcs(std::move(funcs)),
exit_status(exit_status)
{
}
void operator()(const boost::system::error_code & ec_in, int /*signal*/)
{
if (ec_in.value() == boost::asio::error::operation_aborted)
return;
int status;
::wait(&status);
std::error_code ec(ec_in.value(), std::system_category());
int val = WEXITSTATUS(status);
exit_status->store(status);
for (auto & func : funcs)
func(val, ec);
}
};
private:
boost::asio::io_service &ios;
boost::asio::io_context &ios;
boost::process::detail::posix::sigchld_service &sigchld_service = boost::asio::use_service<boost::process::detail::posix::sigchld_service>(ios);
};
}}}}
#endif /* BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_ */
#endif /* BOOST_PROCESS_WINDOWS_IO_CONTEXT_REF_HPP_ */

View File

@@ -13,37 +13,25 @@
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 = 0x017f;
static_assert(WIFSTOPPED(still_active), "Expected still_active to indicate WIFSTOPPED");
static_assert(!WIFEXITED(still_active), "Expected still_active to not indicate WIFEXITED");
static_assert(!WIFSIGNALED(still_active), "Expected still_active to not indicate WIFSIGNALED");
static_assert(!WIFCONTINUED(still_active), "Expected still_active to not indicate WIFCONTINUED");
constexpr int still_active = 0x7F;
static_assert(!WIFEXITED(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 +43,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;
}
}
}}}}

View File

@@ -23,11 +23,11 @@ struct on_exit_ : boost::process::detail::posix::async_handler
}
template<typename Executor>
std::function<void(int, const std::error_code&)> on_exit_handler(Executor & exec)
std::function<void(int, const std::error_code&)> on_exit_handler(Executor&)
{
return handler;
};
}
};

View File

@@ -24,11 +24,12 @@ inline boost::filesystem::path search_path(
const boost::filesystem::path &filename,
const std::vector<boost::filesystem::path> &path)
{
std::string result;
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 "";

View File

@@ -0,0 +1,135 @@
// Copyright (c) 2017 Klemens D. Morgenstern
//
// 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_SIGCHLD_SERVICE_HPP_
#define BOOST_PROCESS_DETAIL_POSIX_SIGCHLD_SERVICE_HPP_
#include <boost/asio/dispatch.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/signal_set.hpp>
#include <boost/asio/strand.hpp>
#include <boost/optional.hpp>
#include <signal.h>
#include <functional>
#include <sys/wait.h>
namespace boost { namespace process { namespace detail { namespace posix {
class sigchld_service : public boost::asio::detail::service_base<sigchld_service>
{
boost::asio::io_context::strand _strand{get_io_context()};
boost::asio::signal_set _signal_set{get_io_context(), SIGCHLD};
std::vector<std::pair<::pid_t, std::function<void(int, std::error_code)>>> _receivers;
inline void _handle_signal(const boost::system::error_code & ec);
public:
sigchld_service(boost::asio::io_context & io_context)
: boost::asio::detail::service_base<sigchld_service>(io_context)
{
}
template <typename SignalHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(SignalHandler,
void (int, std::error_code))
async_wait(::pid_t pid, SignalHandler && handler)
{
boost::asio::async_completion<
SignalHandler, void(boost::system::error_code)> init{handler};
auto & h = init.completion_handler;
boost::asio::dispatch(
_strand,
[this, pid, h]
{
//check if the child actually is running first
int status;
auto pid_res = ::waitpid(pid, &status, WNOHANG);
if (pid_res < 0)
h(-1, get_last_error());
else if ((pid_res == pid) && (WIFEXITED(status) || WIFSIGNALED(status)))
h(status, {}); //successfully exited already
else //still running
{
if (_receivers.empty())
_signal_set.async_wait(
[this](const boost::system::error_code &ec, int)
{
boost::asio::dispatch(_strand, [this, ec]{this->_handle_signal(ec);});
});
_receivers.emplace_back(pid, h);
}
});
return init.result.get();
}
void shutdown() override
{
_receivers.clear();
}
void cancel()
{
_signal_set.cancel();
}
void cancel(boost::system::error_code & ec)
{
_signal_set.cancel(ec);
}
};
void sigchld_service::_handle_signal(const boost::system::error_code & ec)
{
std::error_code ec_{ec.value(), std::system_category()};
if (ec_)
{
for (auto & r : _receivers)
r.second(-1, ec_);
return;
}
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(
[this](const boost::system::error_code & ec, int)
{
boost::asio::post(_strand, [this, ec]{this->_handle_signal(ec);});
});
}
}
}
}
}
}
#endif

View File

@@ -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

View File

@@ -15,23 +15,10 @@
#include <system_error>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.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;
@@ -41,8 +28,9 @@ 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)));
while (((ret == -1) && (errno == EINTR)) ||
(ret != -1 && !WIFEXITED(status) && !WIFSIGNALED(status)));
if (ret == -1)
ec = boost::process::detail::get_last_error();
else
@@ -50,45 +38,147 @@ 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(
inline void wait(const child_handle &p, int & exit_code) noexcept
{
std::error_code ec;
wait(p, exit_code, ec);
boost::process::detail::throw_error(ec, "waitpid(2) failed in wait");
}
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
{
::sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGCHLD);
auto get_timespec =
[](const Duration & dur)
{
::timespec ts;
ts.tv_sec = std::chrono::duration_cast<std::chrono::seconds>(dur).count();
ts.tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(dur).count() % 1000000000;
return ts;
};
pid_t ret;
int status;
auto start = std::chrono::system_clock::now();
auto time_out = start + rel_time;
struct ::sigaction old_sig;
if (-1 == ::sigaction(SIGCHLD, nullptr, &old_sig))
{
ec = get_last_error();
return false;
}
bool time_out_occured = false;
bool timed_out;
#if defined(BOOST_POSIX_HAS_SIGTIMEDWAIT)
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)));
auto ts = get_timespec(time_out - Clock::now());
auto ret_sig = ::sigtimedwait(&sigset, nullptr, &ts);
errno = 0;
ret = ::waitpid(p.pid, &status, WNOHANG);
if ((ret_sig == SIGCHLD) && (old_sig.sa_handler != SIG_DFL) && (old_sig.sa_handler != SIG_IGN))
old_sig.sa_handler(ret);
if (ret == 0)
{
timed_out = Clock::now() >= time_out;
if (timed_out)
return false;
}
}
while ((ret == 0) ||
(((ret == -1) && errno == EINTR) ||
((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))));
#else
//if we do not have sigtimedwait, we fork off a child process to get the signal in time
pid_t timeout_pid = ::fork();
if (timeout_pid == -1)
{
ec = boost::process::detail::get_last_error();
return true;
}
else if (timeout_pid == 0)
{
auto ts = get_timespec(time_out - Clock::now());
::timespec rem;
::nanosleep(&ts, &rem);
while (rem.tv_sec > 0 || rem.tv_nsec > 0)
::nanosleep(&rem, &rem);
::exit(0);
}
struct child_cleaner_t
{
pid_t pid;
~child_cleaner_t()
{
int res;
::kill(pid, -15);
::waitpid(pid, &res, WNOHANG);
}
};
child_cleaner_t child_cleaner{timeout_pid};
do
{
int ret_sig = 0;
if ((::waitpid(timeout_pid, &status, WNOHANG) != 0)
&& (WIFEXITED(status) || WIFSIGNALED(status)))
ret_sig = ::sigwait(&sigset, nullptr);
errno = 0;
ret = ::waitpid(p.pid, &status, WNOHANG);
if ((ret_sig == SIGCHLD) &&
(old_sig.sa_handler != SIG_DFL) && (old_sig.sa_handler != SIG_IGN))
old_sig.sa_handler(ret);
if (ret <= 0)
{
timed_out = Clock::now() >= time_out;
if (timed_out)
return false;
}
}
while ((ret == 0) ||
(((ret == -1) && errno == EINTR) ||
((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))));
#endif
if (ret == -1)
boost::process::detail::throw_last_error("waitpid(2) failed");
exit_code = status;
ec = boost::process::detail::get_last_error();
else
{
ec.clear();
exit_code = status;
}
return !time_out_occured;
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)
{
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 Rep, class Period >
inline bool wait_for(
@@ -97,107 +187,19 @@ inline bool wait_for(
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;
return wait_until(p, exit_code, std::chrono::steady_clock::now() + rel_time, ec);
}
template< class Rep, class Period >
inline bool wait_until(
inline bool wait_for(
const child_handle &p,
int & exit_code,
const std::chrono::duration<Rep, Period>& time_out)
const std::chrono::duration<Rep, Period>& rel_time)
{
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;
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;
}
}}}}

View File

@@ -12,75 +12,178 @@
#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>
#include <unistd.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)));
if (ret == -1)
boost::process::detail::throw_last_error("waitpid(2) failed");
}
inline void wait(const group_handle &p, std::error_code &ec) noexcept
{
pid_t ret;
int status;
siginfo_t status;
do
{
ret = ::waitpid(-p.grp, &status, 0);
ret = ::waitpid(-p.grp, &status.si_status, 0);
if (ret == -1)
{
ec = get_last_error();
return;
}
//ECHILD --> no child processes left.
ret = ::waitid(P_PGID, p.grp, &status, WEXITED | WNOHANG);
}
while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status)));
if (ret == -1)
while ((ret != -1) || (errno != ECHILD));
if (errno != ECHILD)
ec = boost::process::detail::get_last_error();
else
ec.clear();
}
template< class Rep, class Period >
inline bool wait_for(
inline void wait(const group_handle &p) noexcept
{
std::error_code ec;
wait(p, ec);
boost::process::detail::throw_error(ec, "waitpid(2) failed in wait");
}
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;
::sigset_t sigset;
::siginfo_t siginfo;
auto start = std::chrono::system_clock::now();
auto time_out = start + rel_time;
sigemptyset(&sigset);
sigaddset(&sigset, SIGCHLD);
bool time_out_occured = false;
auto get_timespec =
[](const Duration & dur)
{
::timespec ts;
ts.tv_sec = std::chrono::duration_cast<std::chrono::seconds>(dur).count();
ts.tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(dur).count() % 1000000000;
return ts;
};
bool timed_out = false;
int ret;
struct ::sigaction old_sig;
if (-1 == ::sigaction(SIGCHLD, nullptr, &old_sig))
{
ec = get_last_error();
return false;
}
#if defined(BOOST_POSIX_HAS_SIGTIMEDWAIT)
do
{
ret = ::waitpid(-p.grp, &status, WUNTRACED | WNOHANG);
if (std::chrono::system_clock::now() >= time_out)
auto ts = get_timespec(time_out - Clock::now());
ret = ::sigtimedwait(&sigset, nullptr, &ts);
errno = 0;
if ((ret == SIGCHLD) && (old_sig.sa_handler != SIG_DFL) && (old_sig.sa_handler != SIG_IGN))
old_sig.sa_handler(ret);
ret = ::waitpid(-p.grp, &siginfo.si_status, 0); //so in case it exited, we wanna reap it first
if (ret == -1)
{
time_out_occured = true;
break;
ec = get_last_error();
return false;
}
//check if we're done
ret = ::waitid(P_PGID, p.grp, &siginfo, WEXITED | WNOHANG);
}
while (((ret == -1) && errno == EINTR) ||
((ret != -1) && !WIFEXITED(status)));
while (((ret != -1) || (errno != ECHILD)) && !(timed_out = (Clock::now() > time_out)));
#else
//if we do not have sigtimedwait, we fork off a child process to get the signal in time
pid_t timeout_pid = ::fork();
if (timeout_pid == -1)
{
ec = boost::process::detail::get_last_error();
return true;
}
else if (timeout_pid == 0)
{
auto ts = get_timespec(time_out - Clock::now());
::setpgid(0, p.grp);
::nanosleep(&ts, nullptr);
::exit(0);
}
struct child_cleaner_t
{
pid_t pid;
~child_cleaner_t()
{
int res;
::kill(pid, -15);
::waitpid(pid, &res, WNOHANG);
}
};
child_cleaner_t child_cleaner{timeout_pid};
if (ret == -1)
boost::process::detail::throw_last_error("waitpid(2) failed");
do
{
int ret_sig = 0;
int status;
if ((::waitpid(timeout_pid, &status, WNOHANG) != 0)
&& (WIFEXITED(status) || WIFSIGNALED(status)))
ret = ::sigwait(&sigset, nullptr);
errno = 0;
if ((ret == SIGCHLD) && (old_sig.sa_handler != SIG_DFL) && (old_sig.sa_handler != SIG_IGN))
old_sig.sa_handler(ret);
ret = ::waitpid(-p.grp, &siginfo.si_status, 0); //so in case it exited, we wanna reap it first
if (ret == -1)
{
ec = get_last_error();
return false;
}
//check if we're done
ret = ::waitid(P_PGID, p.grp, &siginfo, WEXITED | WNOHANG);
}
while (((ret != -1) || (errno != ECHILD)) && !(timed_out = (Clock::now() > time_out)));
#endif
if (errno != ECHILD)
{
ec = boost::process::detail::get_last_error();
return !timed_out;
}
else
{
ec.clear();
return true; //even if timed out, there are no child proccessess left
}
return !time_out_occured;
}
template< class Clock, class Duration >
inline bool wait_until(
const group_handle &p,
const std::chrono::time_point<Clock, Duration>& time_out) noexcept
{
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_for(
@@ -88,102 +191,18 @@ inline bool wait_for(
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.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)));
if (ret == -1)
ec = boost::process::detail::get_last_error();
else
ec.clear();
return !time_out_occured;
return wait_until(p, std::chrono::steady_clock::now() + rel_time, ec);
}
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) noexcept
{
pid_t ret;
int status;
auto start = std::chrono::system_clock::now();
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)));
if (ret == -1)
boost::process::detail::throw_last_error("waitpid(2) failed");
return !time_out_occured;
}
template< class Rep, class Period >
inline bool wait_until(
const group_handle &p,
const std::chrono::duration<Rep, Period>& time_out,
std::error_code & ec) noexcept
{
pid_t ret;
int status;
auto start = std::chrono::system_clock::now();
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)));
if (ret == -1)
ec = boost::process::detail::get_last_error();
else
ec.clear();
return !time_out_occured;
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;
}
}}}}

View File

@@ -12,7 +12,7 @@
namespace boost { namespace asio {
class io_service;
class io_context;
}}
namespace boost { namespace process { namespace detail {
@@ -22,7 +22,7 @@ struct async_tag {};
template<>
struct initializer_builder<async_tag>;
template<> struct initializer_tag<::boost::asio::io_service> { typedef async_tag type;};
template<> struct initializer_tag<::boost::asio::io_context> { typedef async_tag type;};

View File

@@ -19,27 +19,43 @@ template<typename Allocator>
class basic_streambuf;
typedef basic_streambuf<std::allocator<char>> streambuf;
class io_service;
class io_context;
class executor;
template <typename Handler>
class basic_yield_context;
namespace windows {
#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
class stream_handle_service;
template <typename StreamHandleService>
class basic_stream_handle;
typedef basic_stream_handle<stream_handle_service> stream_handle;
#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
template <typename Executor>
class basic_stream_handle;
typedef basic_stream_handle<executor> stream_handle;
#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
class object_handle_service;
template <typename ObjectHandleService>
class basic_object_handle;
typedef basic_object_handle<object_handle_service> object_handle;
#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
template <typename Executor>
class basic_object_handle;
typedef basic_object_handle<executor> object_handle;
#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
} //windows
} //asio

View File

@@ -12,9 +12,9 @@
namespace boost { namespace process { namespace detail { namespace windows {
struct require_io_service {};
struct require_io_context {};
struct async_handler : handler_base_ext, require_io_service
struct async_handler : handler_base_ext, require_io_context
{
};
@@ -26,13 +26,13 @@ template<typename T>
struct is_async_handler<const T&> : std::is_base_of<async_handler, T> {};
template<typename T>
struct does_require_io_service : std::is_base_of<require_io_service, T> {};
struct does_require_io_context : std::is_base_of<require_io_context, T> {};
template<typename T>
struct does_require_io_service<T&> : std::is_base_of<require_io_service, T> {};
struct does_require_io_context<T&> : std::is_base_of<require_io_context, T> {};
template<typename T>
struct does_require_io_service<const T&> : std::is_base_of<require_io_service, T> {};
struct does_require_io_context<const T&> : std::is_base_of<require_io_context, T> {};
}}}}

View File

@@ -10,10 +10,10 @@
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_IN_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_IN_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/handle_info.hpp>
#include <boost/detail/winapi/error_codes.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/handle_info.hpp>
#include <boost/winapi/error_codes.hpp>
#include <boost/asio/write.hpp>
#include <boost/process/detail/handler_base.hpp>
@@ -29,7 +29,7 @@ namespace boost { namespace process { namespace detail { namespace windows {
template<typename Buffer>
struct async_in_buffer : ::boost::process::detail::windows::handler_base_ext,
::boost::process::detail::windows::require_io_service
::boost::process::detail::windows::require_io_context
{
Buffer & buf;
@@ -48,28 +48,28 @@ struct async_in_buffer : ::boost::process::detail::windows::handler_base_ext,
template <typename Executor>
inline void on_success(Executor&)
{
auto pipe = this->pipe;
auto pipe_ = this->pipe;
if (this->promise)
{
auto promise = this->promise;
auto promise_ = this->promise;
boost::asio::async_write(*pipe, buf,
[promise](const boost::system::error_code & ec, std::size_t)
boost::asio::async_write(*pipe_, buf,
[promise_](const boost::system::error_code & ec, std::size_t)
{
if (ec && (ec.value() != ::boost::detail::winapi::ERROR_BROKEN_PIPE_))
if (ec && (ec.value() != ::boost::winapi::ERROR_BROKEN_PIPE_))
{
std::error_code e(ec.value(), std::system_category());
promise->set_exception(std::make_exception_ptr(process_error(e)));
promise_->set_exception(std::make_exception_ptr(process_error(e)));
}
promise->set_value();
promise_->set_value();
});
}
else
boost::asio::async_write(*pipe, buf,
[pipe](const boost::system::error_code&, std::size_t){});
boost::asio::async_write(*pipe_, buf,
[pipe_](const boost::system::error_code&, std::size_t){});
std::move(*pipe).source().close();
std::move(*pipe_).source().close();
this->pipe = nullptr;
@@ -78,23 +78,23 @@ struct async_in_buffer : ::boost::process::detail::windows::handler_base_ext,
template<typename Executor>
void on_error(Executor &, const std::error_code &) const
{
::boost::detail::winapi::CloseHandle(pipe->native_source());
::boost::winapi::CloseHandle(pipe->native_source());
}
template <typename WindowsExecutor>
void on_setup(WindowsExecutor &exec)
{
if (!pipe)
pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq));
::boost::detail::winapi::HANDLE_ source_handle = std::move(*pipe).source().native_handle();
::boost::winapi::HANDLE_ source_handle = std::move(*pipe).source().native_handle();
boost::detail::winapi::SetHandleInformation(source_handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
boost::winapi::SetHandleInformation(source_handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
exec.startup_info.hStdInput = source_handle;
exec.startup_info.dwFlags |= boost::detail::winapi::STARTF_USESTDHANDLES_;
exec.startup_info.dwFlags |= boost::winapi::STARTF_USESTDHANDLES_;
exec.inherit_handles = true;
}
};

View File

@@ -10,13 +10,13 @@
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_OUT_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_OUT_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/handle_info.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/handle_info.hpp>
#include <boost/winapi/error_codes.hpp>
#include <boost/asio/read.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/asio_fwd.hpp>
#include <boost/detail/winapi/error_codes.hpp>
#include <istream>
#include <memory>
@@ -30,44 +30,44 @@ namespace boost { namespace process { namespace detail { namespace windows {
template <typename Executor>
inline void apply_out_handles(Executor &e, void* handle, std::integral_constant<int, 1>, std::integral_constant<int, -1>)
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdOutput = handle;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
template <typename Executor>
inline void apply_out_handles(Executor &e, void* handle, std::integral_constant<int, 2>, std::integral_constant<int, -1>)
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdError = handle;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
template <typename Executor>
inline void apply_out_handles(Executor &e, void* handle, std::integral_constant<int, 1>, std::integral_constant<int, 2>)
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdOutput = handle;
e.startup_info.hStdError = handle;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
template<int p1, int p2, typename Buffer>
struct async_out_buffer : ::boost::process::detail::windows::handler_base_ext,
::boost::process::detail::windows::require_io_service
::boost::process::detail::windows::require_io_context
{
Buffer & buf;
@@ -80,10 +80,10 @@ struct async_out_buffer : ::boost::process::detail::windows::handler_base_ext,
template <typename Executor>
inline void on_success(Executor&)
{
auto pipe = this->pipe;
boost::asio::async_read(*pipe, buf,
[pipe](const boost::system::error_code&, std::size_t){});
std::move(*pipe).sink().close();
auto pipe_ = this->pipe;
boost::asio::async_read(*pipe_, buf,
[pipe_](const boost::system::error_code&, std::size_t){});
std::move(*pipe_).sink().close();
this->pipe = nullptr;
}
@@ -98,7 +98,7 @@ struct async_out_buffer : ::boost::process::detail::windows::handler_base_ext,
void on_setup(WindowsExecutor &exec)
{
if (!pipe)
pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq));
apply_out_handles(exec, std::move(*pipe).sink().native_handle(),
std::integral_constant<int, p1>(), std::integral_constant<int, p2>());
}
@@ -108,7 +108,7 @@ struct async_out_buffer : ::boost::process::detail::windows::handler_base_ext,
template<int p1, int p2, typename Type>
struct async_out_future : ::boost::process::detail::windows::handler_base_ext,
::boost::process::detail::windows::require_io_service
::boost::process::detail::windows::require_io_context
{
std::shared_ptr<boost::process::async_pipe> pipe;
std::shared_ptr<std::promise<Type>> promise = std::make_shared<std::promise<Type>>();
@@ -122,31 +122,34 @@ struct async_out_future : ::boost::process::detail::windows::handler_base_ext,
template <typename Executor>
inline void on_success(Executor&)
{
auto pipe = this->pipe;
auto buffer = this->buffer;
auto promise = this->promise;
std::move(*pipe).sink().close();
boost::asio::async_read(*pipe, *buffer,
[pipe, buffer, promise](const boost::system::error_code& ec, std::size_t)
auto pipe_ = this->pipe;
auto buffer_ = this->buffer;
auto promise_ = this->promise;
std::move(*pipe_).sink().close();
boost::asio::async_read(*pipe_, *buffer_,
[pipe_, buffer_, promise_](const boost::system::error_code& ec, std::size_t)
{
if (ec && (ec.value() != ::boost::detail::winapi::ERROR_BROKEN_PIPE_))
if (ec && (ec.value() != ::boost::winapi::ERROR_BROKEN_PIPE_))
{
std::error_code e(ec.value(), std::system_category());
promise->set_exception(std::make_exception_ptr(process_error(e)));
promise_->set_exception(std::make_exception_ptr(process_error(e)));
}
else
{
std::istream is (buffer.get());
std::istream is (buffer_.get());
Type arg;
arg.resize(buffer->size());
is.read(&*arg.begin(), buffer->size());
if (buffer_->size() > 0)
{
arg.resize(buffer_->size());
is.read(&*arg.begin(), buffer_->size());
}
promise->set_value(std::move(arg));
promise_->set_value(std::move(arg));
}
});
this->pipe = nullptr;
this->pipe = nullptr;
this->buffer = nullptr;
this->promise = nullptr;
@@ -163,7 +166,7 @@ struct async_out_future : ::boost::process::detail::windows::handler_base_ext,
void on_setup(WindowsExecutor &exec)
{
if (!pipe)
pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq));
apply_out_handles(exec, std::move(*pipe).sink().native_handle(),
std::integral_constant<int, p1>(), std::integral_constant<int, p2>());

View File

@@ -6,15 +6,17 @@
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_ASYNC_PIPE_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_ASYNC_PIPE_HPP_
#include <boost/detail/winapi/basic_types.hpp>
#include <boost/detail/winapi/pipes.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/file_management.hpp>
#include <boost/detail/winapi/get_last_error.hpp>
#include <boost/detail/winapi/access_rights.hpp>
#include <boost/detail/winapi/process.hpp>
#include <boost/winapi/basic_types.hpp>
#include <boost/winapi/pipes.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/file_management.hpp>
#include <boost/winapi/get_last_error.hpp>
#include <boost/winapi/access_rights.hpp>
#include <boost/winapi/process.hpp>
#include <boost/process/detail/windows/basic_pipe.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/windows/stream_handle.hpp>
#include <atomic>
#include <system_error>
#include <string>
@@ -24,9 +26,9 @@ inline std::string make_pipe_name()
{
std::string name = "\\\\.\\pipe\\boost_process_auto_pipe_";
auto pid = ::boost::detail::winapi::GetCurrentProcessId();
auto pid = ::boost::winapi::GetCurrentProcessId();
static unsigned long long cnt = 0;
static std::atomic_size_t cnt{0};
name += std::to_string(pid);
name += "_";
name += std::to_string(cnt++);
@@ -39,33 +41,33 @@ class async_pipe
::boost::asio::windows::stream_handle _source;
::boost::asio::windows::stream_handle _sink ;
public:
typedef ::boost::detail::winapi::HANDLE_ native_handle_type;
typedef ::boost::winapi::HANDLE_ native_handle_type;
typedef ::boost::asio::windows::stream_handle handle_type;
inline async_pipe(boost::asio::io_service & ios,
inline async_pipe(boost::asio::io_context & ios,
const std::string & name = make_pipe_name())
: async_pipe(ios, ios, name) {}
inline async_pipe(boost::asio::io_service & ios_source,
boost::asio::io_service & ios_sink,
inline async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & ios_sink,
const std::string & name = make_pipe_name());
inline async_pipe(const async_pipe& rhs);
async_pipe(async_pipe&& rhs) : _source(std::move(rhs._source)), _sink(std::move(rhs._sink))
{
rhs._source.assign (::boost::detail::winapi::INVALID_HANDLE_VALUE_);
rhs._sink .assign (::boost::detail::winapi::INVALID_HANDLE_VALUE_);
rhs._source.assign (::boost::winapi::INVALID_HANDLE_VALUE_);
rhs._sink .assign (::boost::winapi::INVALID_HANDLE_VALUE_);
}
template<class CharT, class Traits = std::char_traits<CharT>>
explicit async_pipe(::boost::asio::io_service & ios_source,
::boost::asio::io_service & ios_sink,
explicit async_pipe(::boost::asio::io_context & ios_source,
::boost::asio::io_context & ios_sink,
const basic_pipe<CharT, Traits> & p)
: _source(ios_source, p.native_source()), _sink(ios_sink, p.native_sink())
{
}
template<class CharT, class Traits = std::char_traits<CharT>>
explicit async_pipe(boost::asio::io_service & ios, const basic_pipe<CharT, Traits> & p)
explicit async_pipe(boost::asio::io_context & ios, const basic_pipe<CharT, Traits> & p)
: async_pipe(ios, ios, p)
{
}
@@ -78,10 +80,8 @@ public:
~async_pipe()
{
if (_sink .native() != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
::boost::detail::winapi::CloseHandle(_sink.native());
if (_source.native() != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
::boost::detail::winapi::CloseHandle(_source.native());
boost::system::error_code ec;
close(ec);
}
template<class CharT, class Traits = std::char_traits<CharT>>
@@ -100,12 +100,12 @@ public:
if (_sink.is_open())
{
_sink.close();
_sink = handle_type(_sink.get_io_service());
_sink = handle_type(_sink.get_executor());
}
if (_source.is_open())
{
_source.close();
_source = handle_type(_source.get_io_service());
_source = handle_type(_source.get_executor());
}
}
void close(boost::system::error_code & ec)
@@ -113,12 +113,12 @@ public:
if (_sink.is_open())
{
_sink.close(ec);
_sink = handle_type(_sink.get_io_service());
_sink = handle_type(_sink.get_executor());
}
if (_source.is_open())
{
_source.close(ec);
_source = handle_type(_source.get_io_service());
_source = handle_type(_source.get_executor());
}
}
@@ -129,9 +129,9 @@ public:
void async_close()
{
if (_sink.is_open())
_sink.get_io_service(). post([this]{_sink.close();});
boost::asio::post(_sink.get_executor(), [this]{_sink.close();});
if (_source.is_open())
_source.get_io_service().post([this]{_source.close();});
boost::asio::post(_source.get_executor(), [this]{_source.close();});
}
template<typename MutableBufferSequence>
@@ -145,8 +145,20 @@ public:
return _sink.write_some(buffers);
}
native_handle_type native_source() const {return const_cast<boost::asio::windows::stream_handle&>(_source).native();}
native_handle_type native_sink () const {return const_cast<boost::asio::windows::stream_handle&>(_sink ).native();}
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();}
template<typename MutableBufferSequence,
typename ReadHandler>
@@ -156,7 +168,7 @@ public:
const MutableBufferSequence & buffers,
ReadHandler &&handler)
{
_source.async_read_some(buffers, std::forward<ReadHandler>(handler));
return _source.async_read_some(buffers, std::forward<ReadHandler>(handler));
}
template<typename ConstBufferSequence,
@@ -167,7 +179,7 @@ public:
const ConstBufferSequence & buffers,
WriteHandler && handler)
{
_sink.async_write_some(buffers, std::forward<WriteHandler>(handler));
return _sink.async_write_some(buffers, std::forward<WriteHandler>(handler));
}
const handle_type & sink () const & {return _sink;}
@@ -176,82 +188,82 @@ public:
handle_type && source() && { return std::move(_source); }
handle_type && sink() && { return std::move(_sink); }
handle_type source(::boost::asio::io_service& ios) &&
handle_type source(::boost::asio::io_context& ios) &&
{
::boost::asio::windows::stream_handle stolen(ios, _source.native_handle());
_source.assign(::boost::detail::winapi::INVALID_HANDLE_VALUE_);
::boost::asio::windows::stream_handle stolen(ios.get_executor(), _source.native_handle());
_source.assign(::boost::winapi::INVALID_HANDLE_VALUE_);
return stolen;
}
handle_type sink (::boost::asio::io_service& ios) &&
handle_type sink (::boost::asio::io_context& ios) &&
{
::boost::asio::windows::stream_handle stolen(ios, _sink.native_handle());
_sink.assign(::boost::detail::winapi::INVALID_HANDLE_VALUE_);
::boost::asio::windows::stream_handle stolen(ios.get_executor(), _sink.native_handle());
_sink.assign(::boost::winapi::INVALID_HANDLE_VALUE_);
return stolen;
}
handle_type source(::boost::asio::io_service& ios) const &
handle_type source(::boost::asio::io_context& ios) const &
{
auto proc = ::boost::detail::winapi::GetCurrentProcess();
auto proc = ::boost::winapi::GetCurrentProcess();
::boost::detail::winapi::HANDLE_ source;
auto source_in = const_cast<handle_type&>(_source).native();
if (source_in == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
::boost::winapi::HANDLE_ source;
auto source_in = const_cast<handle_type&>(_source).native_handle();
if (source_in == ::boost::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, source_in, proc, &source, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
return ::boost::asio::windows::stream_handle(ios, source);
return ::boost::asio::windows::stream_handle(ios.get_executor(), source);
}
handle_type sink (::boost::asio::io_service& ios) const &
handle_type sink (::boost::asio::io_context& ios) const &
{
auto proc = ::boost::detail::winapi::GetCurrentProcess();
auto proc = ::boost::winapi::GetCurrentProcess();
::boost::detail::winapi::HANDLE_ sink;
auto sink_in = const_cast<handle_type&>(_sink).native();
if (sink_in == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
::boost::winapi::HANDLE_ sink;
auto sink_in = const_cast<handle_type&>(_sink).native_handle();
if (sink_in == ::boost::winapi::INVALID_HANDLE_VALUE_)
sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, sink_in, proc, &sink, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
return ::boost::asio::windows::stream_handle(ios, sink);
return ::boost::asio::windows::stream_handle(ios.get_executor(), sink);
}
};
async_pipe::async_pipe(const async_pipe& p) :
_source(const_cast<handle_type&>(p._source).get_io_service()),
_sink (const_cast<handle_type&>(p._sink).get_io_service())
_source(const_cast<handle_type&>(p._source).get_executor()),
_sink (const_cast<handle_type&>(p._sink).get_executor())
{
auto proc = ::boost::detail::winapi::GetCurrentProcess();
auto proc = ::boost::winapi::GetCurrentProcess();
::boost::detail::winapi::HANDLE_ source;
::boost::detail::winapi::HANDLE_ sink;
::boost::winapi::HANDLE_ source;
::boost::winapi::HANDLE_ sink;
//cannot get the handle from a const object.
auto source_in = const_cast<handle_type&>(p._source).native();
auto sink_in = const_cast<handle_type&>(p._sink).native();
auto source_in = const_cast<handle_type&>(p._source).native_handle();
auto sink_in = const_cast<handle_type&>(p._sink).native_handle();
if (source_in == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
if (source_in == ::boost::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, source_in, proc, &source, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
if (sink_in == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
if (sink_in == ::boost::winapi::INVALID_HANDLE_VALUE_)
sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, sink_in, proc, &sink, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
_source.assign(source);
@@ -259,32 +271,40 @@ async_pipe::async_pipe(const async_pipe& p) :
}
async_pipe::async_pipe(boost::asio::io_service & ios_source,
boost::asio::io_service & ios_sink,
async_pipe::async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & ios_sink,
const std::string & name) : _source(ios_source), _sink(ios_sink)
{
static constexpr int FILE_FLAG_OVERLAPPED_ = 0x40000000; //temporary
::boost::detail::winapi::HANDLE_ source = ::boost::detail::winapi::create_named_pipe(
::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(),
::boost::detail::winapi::PIPE_ACCESS_INBOUND_
#endif
::boost::winapi::PIPE_ACCESS_INBOUND_
| FILE_FLAG_OVERLAPPED_, //write flag
0, 1, 8192, 8192, 0, nullptr);
if (source == boost::detail::winapi::INVALID_HANDLE_VALUE_)
if (source == boost::winapi::INVALID_HANDLE_VALUE_)
::boost::process::detail::throw_last_error("create_named_pipe(" + name + ") failed");
_source.assign(source);
::boost::detail::winapi::HANDLE_ sink = boost::detail::winapi::create_file(
::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(),
::boost::detail::winapi::GENERIC_WRITE_, 0, nullptr,
::boost::detail::winapi::OPEN_EXISTING_,
#endif
::boost::winapi::GENERIC_WRITE_, 0, nullptr,
::boost::winapi::OPEN_EXISTING_,
FILE_FLAG_OVERLAPPED_, //to allow read
nullptr);
if (sink == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
if (sink == ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::process::detail::throw_last_error("create_file() failed");
_sink.assign(sink);
@@ -292,79 +312,79 @@ async_pipe::async_pipe(boost::asio::io_service & ios_source,
async_pipe& async_pipe::operator=(const async_pipe & p)
{
auto proc = ::boost::detail::winapi::GetCurrentProcess();
auto proc = ::boost::winapi::GetCurrentProcess();
::boost::detail::winapi::HANDLE_ source;
::boost::detail::winapi::HANDLE_ sink;
::boost::winapi::HANDLE_ source;
::boost::winapi::HANDLE_ sink;
//cannot get the handle from a const object.
auto &source_in = const_cast<::boost::asio::windows::stream_handle &>(p._source);
auto &sink_in = const_cast<::boost::asio::windows::stream_handle &>(p._sink);
if (source_in.native() == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
proc, source_in.native(), proc, &source, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
if (source_in.native_handle() == ::boost::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, source_in.native_handle(), proc, &source, 0,
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
if (sink_in.native() == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
proc, sink_in.native(), proc, &sink, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
if (sink_in.native_handle() == ::boost::winapi::INVALID_HANDLE_VALUE_)
sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, sink_in.native_handle(), proc, &sink, 0,
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
//so we also assign the io_service
_source = ::boost::asio::windows::stream_handle(source_in.get_io_service(), source);
_sink = ::boost::asio::windows::stream_handle(source_in.get_io_service(), sink);
//so we also assign the io_context
_source = ::boost::asio::windows::stream_handle(source_in.get_executor(), source);
_sink = ::boost::asio::windows::stream_handle(source_in.get_executor(), sink);
return *this;
}
async_pipe& async_pipe::operator=(async_pipe && rhs)
{
if (_source.native_handle() != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
::boost::detail::winapi::CloseHandle(_source.native());
if (_source.native_handle() != ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::winapi::CloseHandle(_source.native_handle());
if (_sink.native_handle() != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
::boost::detail::winapi::CloseHandle(_sink.native());
if (_sink.native_handle() != ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::winapi::CloseHandle(_sink.native_handle());
_source.assign(rhs._source.native_handle());
_sink .assign(rhs._sink .native_handle());
rhs._source.assign(::boost::detail::winapi::INVALID_HANDLE_VALUE_);
rhs._sink .assign(::boost::detail::winapi::INVALID_HANDLE_VALUE_);
rhs._source.assign(::boost::winapi::INVALID_HANDLE_VALUE_);
rhs._sink .assign(::boost::winapi::INVALID_HANDLE_VALUE_);
return *this;
}
template<class CharT, class Traits>
async_pipe::operator basic_pipe<CharT, Traits>() const
{
auto proc = ::boost::detail::winapi::GetCurrentProcess();
auto proc = ::boost::winapi::GetCurrentProcess();
::boost::detail::winapi::HANDLE_ source;
::boost::detail::winapi::HANDLE_ sink;
::boost::winapi::HANDLE_ source;
::boost::winapi::HANDLE_ sink;
//cannot get the handle from a const object.
auto source_in = const_cast<::boost::asio::windows::stream_handle &>(_source).native();
auto sink_in = const_cast<::boost::asio::windows::stream_handle &>(_sink).native();
auto source_in = const_cast<::boost::asio::windows::stream_handle &>(_source).native_handle();
auto sink_in = const_cast<::boost::asio::windows::stream_handle &>(_sink).native_handle();
if (source_in == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
if (source_in == ::boost::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, source_in, proc, &source, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
if (sink_in == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
if (sink_in == ::boost::winapi::INVALID_HANDLE_VALUE_)
sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, sink_in, proc, &sink, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
return basic_pipe<CharT, Traits>{source, sink};

View File

@@ -67,11 +67,25 @@ inline std::string build_args(const std::string & exe, std::vector<std::string>
inline std::wstring build_args(const std::wstring & exe, std::vector<std::wstring> && data)
{
std::wstring st = exe;
//put in quotes if it has spaces
{
boost::replace_all(st, L"\"", L"\\\"");
auto it = std::find(st.begin(), st.end(), L' ');
if (it != st.end())//contains spaces.
{
st.insert(st.begin(), L'"');
st += L'"';
}
}
for (auto & arg : data)
{
boost::replace_all(arg, L"\"", L"\\\"");
auto it = std::find(arg.begin(), arg.end(), ' ');//contains space?
auto it = std::find(arg.begin(), arg.end(), L' ');//contains space?
if (it != arg.end())//ok, contains spaces.
{
//the first one is put directly onto the output,

View File

@@ -6,14 +6,14 @@
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_PIPE_HPP
#define BOOST_PROCESS_DETAIL_WINDOWS_PIPE_HPP
#include <boost/detail/winapi/basic_types.hpp>
#include <boost/detail/winapi/error_codes.hpp>
#include <boost/detail/winapi/pipes.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/file_management.hpp>
#include <boost/detail/winapi/get_last_error.hpp>
#include <boost/detail/winapi/access_rights.hpp>
#include <boost/detail/winapi/process.hpp>
#include <boost/winapi/basic_types.hpp>
#include <boost/winapi/error_codes.hpp>
#include <boost/winapi/pipes.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/file_management.hpp>
#include <boost/winapi/get_last_error.hpp>
#include <boost/winapi/access_rights.hpp>
#include <boost/winapi/process.hpp>
#include <boost/process/detail/windows/compare_handles.hpp>
#include <system_error>
#include <string>
@@ -24,33 +24,33 @@ namespace boost { namespace process { namespace detail { namespace windows {
template<class CharT, class Traits = std::char_traits<CharT>>
class basic_pipe
{
::boost::detail::winapi::HANDLE_ _source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
::boost::detail::winapi::HANDLE_ _sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
::boost::winapi::HANDLE_ _source = ::boost::winapi::INVALID_HANDLE_VALUE_;
::boost::winapi::HANDLE_ _sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
public:
typedef CharT char_type ;
typedef Traits traits_type;
typedef typename Traits::int_type int_type ;
typedef typename Traits::pos_type pos_type ;
typedef typename Traits::off_type off_type ;
typedef ::boost::detail::winapi::HANDLE_ native_handle_type;
typedef ::boost::winapi::HANDLE_ native_handle_type;
explicit basic_pipe(::boost::detail::winapi::HANDLE_ source, ::boost::detail::winapi::HANDLE_ sink)
explicit basic_pipe(::boost::winapi::HANDLE_ source, ::boost::winapi::HANDLE_ sink)
: _source(source), _sink(sink) {}
inline explicit basic_pipe(const std::string & name);
inline basic_pipe(const basic_pipe& p);
basic_pipe(basic_pipe&& lhs) : _source(lhs._source), _sink(lhs._sink)
{
lhs._source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
lhs._sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
lhs._source = ::boost::winapi::INVALID_HANDLE_VALUE_;
lhs._sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
}
inline basic_pipe& operator=(const basic_pipe& p);
inline basic_pipe& operator=(basic_pipe&& lhs);
~basic_pipe()
{
if (_sink != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
::boost::detail::winapi::CloseHandle(_sink);
if (_source != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
::boost::detail::winapi::CloseHandle(_source);
if (_sink != ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::winapi::CloseHandle(_sink);
if (_source != ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::winapi::CloseHandle(_source);
}
native_handle_type native_source() const {return _source;}
native_handle_type native_sink () const {return _sink;}
@@ -60,21 +60,21 @@ public:
basic_pipe()
{
if (!::boost::detail::winapi::CreatePipe(&_source, &_sink, nullptr, 0))
if (!::boost::winapi::CreatePipe(&_source, &_sink, nullptr, 0))
throw_last_error("CreatePipe() failed");
}
int_type write(const char_type * data, int_type count)
{
::boost::detail::winapi::DWORD_ write_len;
if (!::boost::detail::winapi::WriteFile(
::boost::winapi::DWORD_ write_len;
if (!::boost::winapi::WriteFile(
_sink, data, count * sizeof(char_type), &write_len, nullptr
))
{
auto ec = ::boost::process::detail::get_last_error();
if ((ec.value() == ::boost::detail::winapi::ERROR_BROKEN_PIPE_) ||
(ec.value() == ::boost::detail::winapi::ERROR_NO_DATA_))
if ((ec.value() == ::boost::winapi::ERROR_BROKEN_PIPE_) ||
(ec.value() == ::boost::winapi::ERROR_NO_DATA_))
return 0;
else
throw process_error(ec, "WriteFile failed");
@@ -83,14 +83,14 @@ public:
}
int_type read(char_type * data, int_type count)
{
::boost::detail::winapi::DWORD_ read_len;
if (!::boost::detail::winapi::ReadFile(
::boost::winapi::DWORD_ read_len;
if (!::boost::winapi::ReadFile(
_source, data, count * sizeof(char_type), &read_len, nullptr
))
{
auto ec = ::boost::process::detail::get_last_error();
if ((ec.value() == ::boost::detail::winapi::ERROR_BROKEN_PIPE_) ||
(ec.value() == ::boost::detail::winapi::ERROR_NO_DATA_))
if ((ec.value() == ::boost::winapi::ERROR_BROKEN_PIPE_) ||
(ec.value() == ::boost::winapi::ERROR_NO_DATA_))
return 0;
else
throw process_error(ec, "ReadFile failed");
@@ -100,38 +100,38 @@ public:
bool is_open()
{
return (_source != ::boost::detail::winapi::INVALID_HANDLE_VALUE_) ||
(_sink != ::boost::detail::winapi::INVALID_HANDLE_VALUE_);
return (_source != ::boost::winapi::INVALID_HANDLE_VALUE_) ||
(_sink != ::boost::winapi::INVALID_HANDLE_VALUE_);
}
void close()
{
::boost::detail::winapi::CloseHandle(_source);
::boost::detail::winapi::CloseHandle(_sink);
_source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
_sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
::boost::winapi::CloseHandle(_source);
::boost::winapi::CloseHandle(_sink);
_source = ::boost::winapi::INVALID_HANDLE_VALUE_;
_sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
}
};
template<class Char, class Traits>
basic_pipe<Char, Traits>::basic_pipe(const basic_pipe & p)
{
auto proc = ::boost::detail::winapi::GetCurrentProcess();
auto proc = ::boost::winapi::GetCurrentProcess();
if (p._source == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
_source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
if (p._source == ::boost::winapi::INVALID_HANDLE_VALUE_)
_source = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, p._source, proc, &_source, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
if (p._sink == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
_sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
if (p._sink == ::boost::winapi::INVALID_HANDLE_VALUE_)
_sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, p._sink, proc, &_sink, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
}
@@ -143,23 +143,28 @@ basic_pipe<Char, Traits>::basic_pipe(const std::string & name)
static constexpr int FILE_FLAG_OVERLAPPED_ = 0x40000000; //temporary
//static constexpr int FILE_ATTRIBUTE_NORMAL_ = 0x00000080; //temporary
::boost::detail::winapi::HANDLE_ source = ::boost::detail::winapi::create_named_pipe(
name.c_str(),
::boost::detail::winapi::PIPE_ACCESS_INBOUND_
#if BOOST_NO_ANSI_APIS
std::wstring name_ = boost::process::detail::convert(name);
#else
auto &name_ = name;
#endif
::boost::winapi::HANDLE_ source = ::boost::winapi::create_named_pipe(
name_.c_str(),
::boost::winapi::PIPE_ACCESS_INBOUND_
| FILE_FLAG_OVERLAPPED_, //write flag
0, 1, 8192, 8192, 0, nullptr);
if (source == boost::detail::winapi::INVALID_HANDLE_VALUE_)
if (source == boost::winapi::INVALID_HANDLE_VALUE_)
::boost::process::detail::throw_last_error("create_named_pipe() failed");
::boost::detail::winapi::HANDLE_ sink = boost::detail::winapi::create_file(
::boost::winapi::HANDLE_ sink = boost::winapi::create_file(
name.c_str(),
::boost::detail::winapi::GENERIC_WRITE_, 0, nullptr,
::boost::winapi::GENERIC_WRITE_, 0, nullptr,
OPEN_EXISTING_,
FILE_FLAG_OVERLAPPED_, //to allow read
nullptr);
if (sink == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
if (sink == ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::process::detail::throw_last_error("create_file() failed");
_source = source;
@@ -169,22 +174,22 @@ basic_pipe<Char, Traits>::basic_pipe(const std::string & name)
template<class Char, class Traits>
basic_pipe<Char, Traits>& basic_pipe<Char, Traits>::operator=(const basic_pipe & p)
{
auto proc = ::boost::detail::winapi::GetCurrentProcess();
auto proc = ::boost::winapi::GetCurrentProcess();
if (p._source == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
_source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
if (p._source == ::boost::winapi::INVALID_HANDLE_VALUE_)
_source = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, p._source, proc, &_source, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
if (p._sink == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
_sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::detail::winapi::DuplicateHandle(
if (p._sink == ::boost::winapi::INVALID_HANDLE_VALUE_)
_sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, p._sink, proc, &_sink, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
return *this;
@@ -193,16 +198,16 @@ basic_pipe<Char, Traits>& basic_pipe<Char, Traits>::operator=(const basic_pipe &
template<class Char, class Traits>
basic_pipe<Char, Traits>& basic_pipe<Char, Traits>::operator=(basic_pipe && lhs)
{
if (_source != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
::boost::detail::winapi::CloseHandle(_source);
if (_source != ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::winapi::CloseHandle(_source);
if (_sink != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
::boost::detail::winapi::CloseHandle(_sink);
if (_sink != ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::winapi::CloseHandle(_sink);
_source = lhs._source;
_sink = lhs._sink;
lhs._source = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
lhs._sink = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
lhs._source = ::boost::winapi::INVALID_HANDLE_VALUE_;
lhs._sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
return *this;
}

View File

@@ -11,9 +11,9 @@
#define BOOST_PROCESS_WINDOWS_CHILD_HPP
#include <boost/move/move.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/jobs.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/jobs.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
@@ -21,18 +21,18 @@ typedef int pid_t;
struct child_handle
{
::boost::detail::winapi::PROCESS_INFORMATION_ proc_info{nullptr, nullptr, 0,0};
::boost::winapi::PROCESS_INFORMATION_ proc_info{nullptr, nullptr, 0,0};
explicit child_handle(const ::boost::detail::winapi::PROCESS_INFORMATION_ &pi) :
explicit child_handle(const ::boost::winapi::PROCESS_INFORMATION_ &pi) :
proc_info(pi)
{}
explicit child_handle(pid_t pid) :
proc_info{nullptr, nullptr, 0,0}
{
auto h = ::boost::detail::winapi::OpenProcess(
::boost::detail::winapi::PROCESS_ALL_ACCESS_,
static_cast<::boost::detail::winapi::BOOL_>(0),
auto h = ::boost::winapi::OpenProcess(
::boost::winapi::PROCESS_ALL_ACCESS_,
static_cast<::boost::winapi::BOOL_>(0),
pid);
if (h == nullptr)
@@ -44,23 +44,23 @@ struct child_handle
child_handle() = default;
~child_handle()
{
::boost::detail::winapi::CloseHandle(proc_info.hProcess);
::boost::detail::winapi::CloseHandle(proc_info.hThread);
::boost::winapi::CloseHandle(proc_info.hProcess);
::boost::winapi::CloseHandle(proc_info.hThread);
}
child_handle(const child_handle & c) = delete;
child_handle(child_handle && c) : proc_info(c.proc_info)
{
c.proc_info.hProcess = ::boost::detail::winapi::invalid_handle_value;
c.proc_info.hThread = ::boost::detail::winapi::invalid_handle_value;
c.proc_info.hProcess = ::boost::winapi::invalid_handle_value;
c.proc_info.hThread = ::boost::winapi::invalid_handle_value;
}
child_handle &operator=(const child_handle & c) = delete;
child_handle &operator=(child_handle && c)
{
::boost::detail::winapi::CloseHandle(proc_info.hProcess);
::boost::detail::winapi::CloseHandle(proc_info.hThread);
::boost::winapi::CloseHandle(proc_info.hProcess);
::boost::winapi::CloseHandle(proc_info.hThread);
proc_info = c.proc_info;
c.proc_info.hProcess = ::boost::detail::winapi::invalid_handle_value;
c.proc_info.hThread = ::boost::detail::winapi::invalid_handle_value;
c.proc_info.hProcess = ::boost::winapi::invalid_handle_value;
c.proc_info.hThread = ::boost::winapi::invalid_handle_value;
return *this;
}
@@ -69,25 +69,25 @@ struct child_handle
return static_cast<int>(proc_info.dwProcessId);
}
typedef ::boost::detail::winapi::HANDLE_ process_handle_t;
typedef ::boost::winapi::HANDLE_ process_handle_t;
process_handle_t process_handle() const { return proc_info.hProcess; }
bool valid() const
{
return (proc_info.hProcess != nullptr) &&
(proc_info.hProcess != ::boost::detail::winapi::INVALID_HANDLE_VALUE_);
(proc_info.hProcess != ::boost::winapi::INVALID_HANDLE_VALUE_);
}
bool in_group() const
{
::boost::detail::winapi::BOOL_ value;
if (!::boost::detail::winapi::IsProcessInJob(proc_info.hProcess, nullptr, &value))
::boost::winapi::BOOL_ value;
if (!::boost::winapi::IsProcessInJob(proc_info.hProcess, nullptr, &value))
throw_last_error("IsProcessinJob Failed");
return value!=0;
}
bool in_group(std::error_code &ec) const noexcept
{
::boost::detail::winapi::BOOL_ value;
if (!::boost::detail::winapi::IsProcessInJob(proc_info.hProcess, nullptr, &value))
::boost::winapi::BOOL_ value;
if (!::boost::winapi::IsProcessInJob(proc_info.hProcess, nullptr, &value))
ec = get_last_error();
return value!=0;
}

View File

@@ -10,8 +10,8 @@
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_IN_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_IN_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/process/detail/handler_base.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
@@ -21,8 +21,8 @@ struct close_in : public ::boost::process::detail::handler_base
template <class WindowsExecutor>
void on_setup(WindowsExecutor &e) const
{
e.startup_info.hStdInput = boost::detail::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.dwFlags |= boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.hStdInput = boost::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.dwFlags |= boost::winapi::STARTF_USESTDHANDLES_;
}
};

View File

@@ -10,8 +10,8 @@
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_OUT_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_CLOSE_OUT_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/process/detail/handler_base.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
@@ -27,25 +27,25 @@ template<>
template<typename WindowsExecutor>
void close_out<1,-1>::on_setup(WindowsExecutor &e) const
{
e.startup_info.hStdOutput = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.hStdOutput = ::boost::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
}
template<>
template<typename WindowsExecutor>
void close_out<2,-1>::on_setup(WindowsExecutor &e) const
{
e.startup_info.hStdError = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.hStdError = ::boost::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
}
template<>
template<typename WindowsExecutor>
void close_out<1,2>::on_setup(WindowsExecutor &e) const
{
e.startup_info.hStdOutput = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.hStdError = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.hStdOutput = ::boost::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.hStdError = ::boost::winapi::INVALID_HANDLE_VALUE_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
}
}}}}

View File

@@ -6,28 +6,28 @@
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_COMPARE_HANDLES_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_COMPARE_HANDLES_HPP_
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/file_management.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/file_management.hpp>
#include <boost/process/detail/config.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
inline bool compare_handles(boost::detail::winapi::HANDLE_ lhs, boost::detail::winapi::HANDLE_ rhs)
inline bool compare_handles(boost::winapi::HANDLE_ lhs, boost::winapi::HANDLE_ rhs)
{
if ( (lhs == ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
|| (rhs == ::boost::detail::winapi::INVALID_HANDLE_VALUE_))
if ( (lhs == ::boost::winapi::INVALID_HANDLE_VALUE_)
|| (rhs == ::boost::winapi::INVALID_HANDLE_VALUE_))
return false;
if (lhs == rhs)
return true;
::boost::detail::winapi::BY_HANDLE_FILE_INFORMATION_ lhs_info{0,{0,0},{0,0},{0,0},0,0,0,0,0,0};
::boost::detail::winapi::BY_HANDLE_FILE_INFORMATION_ rhs_info{0,{0,0},{0,0},{0,0},0,0,0,0,0,0};
::boost::winapi::BY_HANDLE_FILE_INFORMATION_ lhs_info{0,{0,0},{0,0},{0,0},0,0,0,0,0,0};
::boost::winapi::BY_HANDLE_FILE_INFORMATION_ rhs_info{0,{0,0},{0,0},{0,0},0,0,0,0,0,0};
if (!::boost::detail::winapi::GetFileInformationByHandle(lhs, &lhs_info))
if (!::boost::winapi::GetFileInformationByHandle(lhs, &lhs_info))
::boost::process::detail::throw_last_error("GetFileInformationByHandle");
if (!::boost::detail::winapi::GetFileInformationByHandle(rhs, &rhs_info))
if (!::boost::winapi::GetFileInformationByHandle(rhs, &rhs_info))
::boost::process::detail::throw_last_error("GetFileInformationByHandle");
return (lhs_info.nFileIndexHigh == rhs_info.nFileIndexHigh)

View File

@@ -7,8 +7,8 @@
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_ENV_INIT_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_ENV_INIT_HPP_
#include <boost/detail/winapi/error_codes.hpp>
#include <boost/detail/winapi/process.hpp>
#include <boost/winapi/error_codes.hpp>
#include <boost/winapi/process.hpp>
#include <boost/process/detail/config.hpp>
@@ -25,10 +25,10 @@ struct env_init : public ::boost::process::detail::handler_base
env_init(boost::process::basic_environment<Char> && env) : env(std::move(env)) {};
env_init(const boost::process::basic_environment<Char> & env) : env(env) {};
constexpr static ::boost::detail::winapi::DWORD_ creation_flag(char) {return 0u;}
constexpr static ::boost::detail::winapi::DWORD_ creation_flag(wchar_t)
constexpr static ::boost::winapi::DWORD_ creation_flag(char) {return 0u;}
constexpr static ::boost::winapi::DWORD_ creation_flag(wchar_t)
{
return ::boost::detail::winapi::CREATE_UNICODE_ENVIRONMENT_;
return ::boost::winapi::CREATE_UNICODE_ENVIRONMENT_;
}
template <class WindowsExecutor>
@@ -37,7 +37,7 @@ struct env_init : public ::boost::process::detail::handler_base
auto e = env.native_handle();
if (*e == null_char<char>())
{
exec.set_error(std::error_code(::boost::detail::winapi::ERROR_BAD_ENVIRONMENT_, std::system_category()),
exec.set_error(std::error_code(::boost::winapi::ERROR_BAD_ENVIRONMENT_, std::system_category()),
"Empty Environment");
}

View File

@@ -9,11 +9,11 @@
#include <string>
#include <vector>
#include <unordered_map>
#include <boost/detail/winapi/error_codes.hpp>
#include <boost/detail/winapi/environment.hpp>
#include <boost/winapi/error_codes.hpp>
#include <boost/winapi/environment.hpp>
#include <boost/winapi/get_current_process.hpp>
#include <boost/winapi/get_current_process_id.hpp>
#include <boost/process/detail/config.hpp>
#include <boost/detail/winapi/get_current_process.hpp>
#include <boost/detail/winapi/get_current_process_id.hpp>
#include <algorithm>
#include <boost/process/locale.hpp>
@@ -22,8 +22,8 @@ namespace boost { namespace process { namespace detail { namespace windows {
template<typename Char>
class native_environment_impl
{
static void _deleter(Char* p) {boost::detail::winapi::free_environment_strings(p);};
std::unique_ptr<Char[], void(*)(Char*)> _buf{boost::detail::winapi::get_environment_strings<Char>(), &native_environment_impl::_deleter};
static void _deleter(Char* p) {boost::winapi::free_environment_strings(p);};
std::unique_ptr<Char[], void(*)(Char*)> _buf{boost::winapi::get_environment_strings<Char>(), &native_environment_impl::_deleter};
static inline std::vector<Char*> _load_var(Char* p);
std::vector<Char*> _env_arr{_load_var(_buf.get())};
public:
@@ -33,7 +33,7 @@ public:
using native_handle_type = pointer_type;
void reload()
{
_buf.reset(boost::detail::winapi::get_environment_strings<Char>());
_buf.reset(boost::winapi::get_environment_strings<Char>());
_env_arr = _load_var(_buf.get());
_env_impl = &*_env_arr.begin();
}
@@ -60,11 +60,11 @@ template<typename Char>
inline auto native_environment_impl<Char>::get(const pointer_type id) -> string_type
{
Char buf[4096];
auto size = boost::detail::winapi::get_environment_variable(id, buf, sizeof(buf));
auto size = boost::winapi::get_environment_variable(id, buf, sizeof(buf));
if (size == 0) //failed
{
auto err = ::boost::detail::winapi::GetLastError();
if (err == ::boost::detail::winapi::ERROR_ENVVAR_NOT_FOUND_)//well, then we consider that an empty value
auto err = ::boost::winapi::GetLastError();
if (err == ::boost::winapi::ERROR_ENVVAR_NOT_FOUND_)//well, then we consider that an empty value
return "";
else
throw process_error(std::error_code(err, std::system_category()),
@@ -82,7 +82,7 @@ inline auto native_environment_impl<Char>::get(const pointer_type id) -> string_
while (buf_size <= max_size)
{
std::vector<Char> buf(buf_size);
auto size = boost::detail::winapi::get_environment_variable(id, buf.data(), buf.size());
auto size = boost::winapi::get_environment_variable(id, buf.data(), buf.size());
if (size == buf_size) //buffer to small
buf_size *= 2;
@@ -101,13 +101,13 @@ inline auto native_environment_impl<Char>::get(const pointer_type id) -> string_
template<typename Char>
inline void native_environment_impl<Char>::set(const pointer_type id, const pointer_type value)
{
boost::detail::winapi::set_environment_variable(id, value);
boost::winapi::set_environment_variable(id, value);
}
template<typename Char>
inline void native_environment_impl<Char>::reset(const pointer_type id)
{
boost::detail::winapi::set_environment_variable(id, nullptr);
boost::winapi::set_environment_variable(id, nullptr);
}
template<typename Char>
@@ -300,10 +300,8 @@ inline void basic_environment_impl<Char>::reset(const string_type &id)
auto end = itr;
while (*end != '\0')
end++;
while (*++end != '\0');
end ++; //to point behind the last null-char
_data.erase(itr, end);//and remove it
reload();
@@ -339,8 +337,8 @@ template<typename T> constexpr T env_seperator();
template<> constexpr char env_seperator() {return ';'; }
template<> constexpr wchar_t env_seperator() {return L';'; }
inline int get_id() {return boost::detail::winapi::GetCurrentProcessId();}
inline void* native_handle() {return boost::detail::winapi::GetCurrentProcess(); }
inline int get_id() {return boost::winapi::GetCurrentProcessId();}
inline void* native_handle() {return boost::winapi::GetCurrentProcess(); }
typedef void* native_handle_t;

View File

@@ -16,8 +16,8 @@
#include <boost/process/detail/traits.hpp>
#include <boost/process/error.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/process.hpp>
#include <boost/none.hpp>
#include <system_error>
#include <memory>
@@ -33,13 +33,13 @@ template<typename CharType> struct startup_info;
template<> struct startup_info<char>
{
typedef ::boost::detail::winapi::STARTUPINFOA_ type;
typedef ::boost::winapi::STARTUPINFOA_ type;
};
#endif
template<> struct startup_info<wchar_t>
{
typedef ::boost::detail::winapi::STARTUPINFOW_ type;
typedef ::boost::winapi::STARTUPINFOW_ type;
};
#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
@@ -49,13 +49,13 @@ template<typename CharType> struct startup_info_ex;
#if !defined( BOOST_NO_ANSI_APIS )
template<> struct startup_info_ex<char>
{
typedef ::boost::detail::winapi::STARTUPINFOEXA_ type;
typedef ::boost::winapi::STARTUPINFOEXA_ type;
};
#endif
template<> struct startup_info_ex<wchar_t>
{
typedef ::boost::detail::winapi::STARTUPINFOEXW_ type;
typedef ::boost::winapi::STARTUPINFOEXW_ type;
};
@@ -66,7 +66,7 @@ template<> struct startup_info_ex<wchar_t>
template<typename CharT>
struct startup_info_impl
{
::boost::detail::winapi::DWORD_ creation_flags = 0;
::boost::winapi::DWORD_ creation_flags = 0;
typedef typename startup_info_ex<CharT>::type startup_info_ex_t;
typedef typename startup_info<CharT>::type startup_info_t;
@@ -74,9 +74,9 @@ struct startup_info_impl
startup_info_ex_t startup_info_ex
{startup_info_t {sizeof(startup_info_t), nullptr, nullptr, nullptr,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr,
::boost::detail::winapi::invalid_handle_value,
::boost::detail::winapi::invalid_handle_value,
::boost::detail::winapi::invalid_handle_value},
::boost::winapi::invalid_handle_value,
::boost::winapi::invalid_handle_value,
::boost::winapi::invalid_handle_value},
nullptr
};
startup_info_t & startup_info = startup_info_ex.StartupInfo;
@@ -84,7 +84,7 @@ struct startup_info_impl
void set_startup_info_ex()
{
startup_info.cb = sizeof(startup_info_ex_t);
creation_flags = ::boost::detail::winapi::EXTENDED_STARTUPINFO_PRESENT_;
creation_flags |= ::boost::winapi::EXTENDED_STARTUPINFO_PRESENT_;
}
};
@@ -96,13 +96,13 @@ struct startup_info_impl
{
typedef typename startup_info<CharT>::type startup_info_t;
::boost::detail::winapi::DWORD_ creation_flags = 0;
::boost::winapi::DWORD_ creation_flags = 0;
startup_info_t startup_info
{sizeof(startup_info_t), nullptr, nullptr, nullptr,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr,
::boost::detail::winapi::invalid_handle_value,
::boost::detail::winapi::invalid_handle_value,
::boost::detail::winapi::invalid_handle_value};
::boost::winapi::invalid_handle_value,
::boost::winapi::invalid_handle_value,
::boost::winapi::invalid_handle_value};
};
#endif
@@ -186,7 +186,7 @@ public:
}
//NOTE: The non-cast cmd-line string can only be modified by the wchar_t variant which is currently disabled.
int err_code = ::boost::detail::winapi::create_process(
int err_code = ::boost::winapi::create_process(
exe, // LPCSTR_ lpApplicationName,
const_cast<Char*>(cmd_line), // LPSTR_ lpCommandLine,
proc_attrs, // LPSECURITY_ATTRIBUTES_ lpProcessAttributes,
@@ -232,9 +232,9 @@ public:
const std::error_code& error() const {return _ec;}
::boost::detail::winapi::LPSECURITY_ATTRIBUTES_ proc_attrs = nullptr;
::boost::detail::winapi::LPSECURITY_ATTRIBUTES_ thread_attrs = nullptr;
::boost::detail::winapi::BOOL_ inherit_handles = false;
::boost::winapi::LPSECURITY_ATTRIBUTES_ proc_attrs = nullptr;
::boost::winapi::LPSECURITY_ATTRIBUTES_ thread_attrs = nullptr;
::boost::winapi::BOOL_ inherit_handles = false;
const Char * work_dir = nullptr;
const Char * cmd_line = nullptr;
const Char * exe = nullptr;
@@ -242,7 +242,7 @@ public:
Sequence & seq;
::boost::detail::winapi::PROCESS_INFORMATION_ proc_info{nullptr, nullptr, 0,0};
::boost::winapi::PROCESS_INFORMATION_ proc_info{nullptr, nullptr, 0,0};
};

View File

@@ -6,9 +6,9 @@
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_FILE_DESCRIPTOR_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_FILE_DESCRIPTOR_HPP_
#include <boost/detail/winapi/basic_types.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/file_management.hpp>
#include <boost/winapi/basic_types.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/file_management.hpp>
#include <string>
#include <boost/filesystem/path.hpp>
@@ -22,17 +22,17 @@ struct file_descriptor
write = 2,
read_write = 3
};
static ::boost::detail::winapi::DWORD_ desired_access(mode_t mode)
static ::boost::winapi::DWORD_ desired_access(mode_t mode)
{
switch(mode)
{
case read:
return ::boost::detail::winapi::GENERIC_READ_;
return ::boost::winapi::GENERIC_READ_;
case write:
return ::boost::detail::winapi::GENERIC_WRITE_;
return ::boost::winapi::GENERIC_WRITE_;
case read_write:
return ::boost::detail::winapi::GENERIC_READ_
| ::boost::detail::winapi::GENERIC_WRITE_;
return ::boost::winapi::GENERIC_READ_
| ::boost::winapi::GENERIC_WRITE_;
default:
return 0u;
}
@@ -45,37 +45,45 @@ 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::detail::winapi::create_file(
::boost::winapi::create_file(
path,
desired_access(mode),
::boost::detail::winapi::FILE_SHARE_READ_ |
::boost::detail::winapi::FILE_SHARE_WRITE_,
::boost::winapi::FILE_SHARE_READ_ |
::boost::winapi::FILE_SHARE_WRITE_,
nullptr,
::boost::detail::winapi::OPEN_ALWAYS_,
::boost::winapi::OPEN_ALWAYS_,
::boost::detail::winapi::FILE_ATTRIBUTE_NORMAL_,
::boost::winapi::FILE_ATTRIBUTE_NORMAL_,
nullptr
))
#endif
{
}
file_descriptor(const wchar_t * path, mode_t mode = read_write)
: _handle(
::boost::detail::winapi::create_file(
::boost::winapi::create_file(
path,
desired_access(mode),
::boost::detail::winapi::FILE_SHARE_READ_ |
::boost::detail::winapi::FILE_SHARE_WRITE_,
::boost::winapi::FILE_SHARE_READ_ |
::boost::winapi::FILE_SHARE_WRITE_,
nullptr,
::boost::detail::winapi::OPEN_ALWAYS_,
::boost::winapi::OPEN_ALWAYS_,
::boost::detail::winapi::FILE_ATTRIBUTE_NORMAL_,
::boost::winapi::FILE_ATTRIBUTE_NORMAL_,
nullptr
))
{
@@ -89,14 +97,14 @@ struct file_descriptor
~file_descriptor()
{
if (_handle != ::boost::detail::winapi::INVALID_HANDLE_VALUE_)
::boost::detail::winapi::CloseHandle(_handle);
if (_handle != ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::winapi::CloseHandle(_handle);
}
::boost::detail::winapi::HANDLE_ handle() const { return _handle;}
::boost::winapi::HANDLE_ handle() const { return _handle;}
private:
::boost::detail::winapi::HANDLE_ _handle = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
::boost::winapi::HANDLE_ _handle = ::boost::winapi::INVALID_HANDLE_VALUE_;
};
}}}}

View File

@@ -10,8 +10,8 @@
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_FILE_IN_HPP
#define BOOST_PROCESS_DETAIL_WINDOWS_FILE_IN_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/file_descriptor.hpp>
#include <io.h>
@@ -21,20 +21,20 @@ namespace boost { namespace process { namespace detail { namespace windows {
struct file_in : public ::boost::process::detail::handler_base
{
file_descriptor file;
::boost::detail::winapi::HANDLE_ handle = file.handle();
::boost::winapi::HANDLE_ handle = file.handle();
template<typename T>
file_in(T&& t) : file(std::forward<T>(t), file_descriptor::read) {}
file_in(FILE * f) : handle(reinterpret_cast<::boost::detail::winapi::HANDLE_>(_get_osfhandle(_fileno(f)))) {}
file_in(FILE * f) : handle(reinterpret_cast<::boost::winapi::HANDLE_>(_get_osfhandle(_fileno(f)))) {}
template <class WindowsExecutor>
void on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdInput = handle;
e.startup_info.dwFlags |= boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.dwFlags |= boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
};

View File

@@ -10,9 +10,9 @@
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_FILE_OUT_HPP
#define BOOST_PROCESS_DETAIL_WINDOWS_FILE_OUT_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/handle_info.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/handle_info.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/file_descriptor.hpp>
@@ -22,7 +22,7 @@ template<int p1, int p2>
struct file_out : public ::boost::process::detail::handler_base
{
file_descriptor file;
::boost::detail::winapi::HANDLE_ handle = file.handle();
::boost::winapi::HANDLE_ handle = file.handle();
template<typename T>
file_out(T&& t) : file(std::forward<T>(t), file_descriptor::write) {}
@@ -36,12 +36,12 @@ template<>
template<typename WindowsExecutor>
void file_out<1,-1>::on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdOutput = handle;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
@@ -49,12 +49,12 @@ template<>
template<typename WindowsExecutor>
void file_out<2,-1>::on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdError = handle;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
@@ -62,13 +62,13 @@ template<>
template<typename WindowsExecutor>
void file_out<1,2>::on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdOutput = handle;
e.startup_info.hStdError = handle;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}

View File

@@ -7,14 +7,14 @@
#define BOOST_PROCESS_DETAIL_WINDOWS_GROUP_HPP_
#include <boost/process/detail/windows/handler.hpp>
#include <boost/detail/winapi/jobs.hpp>
#include <boost/winapi/jobs.hpp>
#include <boost/process/detail/windows/child_handle.hpp>
#include <boost/process/detail/windows/job_workaround.hpp>
#include <system_error>
namespace boost { namespace process { namespace detail { namespace windows {
inline bool break_away_enabled(::boost::detail::winapi::HANDLE_ h)
inline bool break_away_enabled(::boost::winapi::HANDLE_ h)
{
workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;
@@ -29,7 +29,7 @@ inline bool break_away_enabled(::boost::detail::winapi::HANDLE_ h)
return (info.BasicLimitInformation.LimitFlags & workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_) != 0;
}
inline void enable_break_away(::boost::detail::winapi::HANDLE_ h)
inline void enable_break_away(::boost::winapi::HANDLE_ h)
{
workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;
@@ -54,7 +54,7 @@ inline void enable_break_away(::boost::detail::winapi::HANDLE_ h)
throw_last_error("SetInformationJobObject() failed");
}
inline void enable_break_away(::boost::detail::winapi::HANDLE_ h, std::error_code & ec)
inline void enable_break_away(::boost::winapi::HANDLE_ h, std::error_code & ec)
{
workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;
@@ -84,71 +84,92 @@ inline void enable_break_away(::boost::detail::winapi::HANDLE_ h, std::error_cod
ec = get_last_error();
return;
}
}
inline void associate_completion_port(::boost::winapi::HANDLE_ job,
::boost::winapi::HANDLE_ io_port)
{
workaround::JOBOBJECT_ASSOCIATE_COMPLETION_PORT_ port;
port.CompletionKey = job;
port.CompletionPort = io_port;
if (!workaround::set_information_job_object(
job,
workaround::JobObjectAssociateCompletionPortInformation_,
static_cast<void*>(&port),
sizeof(port)))
throw_last_error("SetInformationJobObject() failed");
}
struct group_handle
{
::boost::detail::winapi::HANDLE_ _job_object;
::boost::winapi::HANDLE_ _job_object;
::boost::winapi::HANDLE_ _io_port;
typedef ::boost::detail::winapi::HANDLE_ handle_t;
typedef ::boost::winapi::HANDLE_ handle_t;
handle_t handle() const { return _job_object; }
explicit group_handle(handle_t h) :
_job_object(h)
_job_object(h),
_io_port(::CreateIoCompletionPort(::boost::winapi::INVALID_HANDLE_VALUE_, nullptr, 0, 1))
{
enable_break_away(_job_object);
associate_completion_port(_job_object, _io_port);
}
group_handle() : group_handle(::boost::detail::winapi::CreateJobObjectA(nullptr, nullptr))
group_handle() : group_handle(::boost::winapi::CreateJobObjectW(nullptr, nullptr))
{
}
~group_handle()
{
::boost::detail::winapi::CloseHandle(_job_object);
::boost::winapi::CloseHandle(_job_object);
::boost::winapi::CloseHandle(_io_port);
}
group_handle(const group_handle & c) = delete;
group_handle(group_handle && c) : _job_object(c._job_object)
group_handle(group_handle && c) : _job_object(c._job_object),
_io_port(c._io_port)
{
c._job_object = ::boost::detail::winapi::invalid_handle_value;
c._job_object = ::boost::winapi::invalid_handle_value;
c._io_port = ::boost::winapi::invalid_handle_value;
}
group_handle &operator=(const group_handle & c) = delete;
group_handle &operator=(group_handle && c)
{
::boost::winapi::CloseHandle(_io_port);
_io_port = c._io_port;
c._io_port = ::boost::winapi::invalid_handle_value;
::boost::detail::winapi::CloseHandle(_job_object);
::boost::winapi::CloseHandle(_job_object);
_job_object = c._job_object;
c._job_object = ::boost::detail::winapi::invalid_handle_value;
c._job_object = ::boost::winapi::invalid_handle_value;
return *this;
}
void add(handle_t proc)
{
if (!::boost::detail::winapi::AssignProcessToJobObject(_job_object, proc))
if (!::boost::winapi::AssignProcessToJobObject(_job_object, proc))
throw_last_error();
}
void add(handle_t proc, std::error_code & ec) noexcept
{
if (!::boost::detail::winapi::AssignProcessToJobObject(_job_object, proc))
if (!::boost::winapi::AssignProcessToJobObject(_job_object, proc))
ec = get_last_error();
}
bool has(handle_t proc)
{
::boost::detail::winapi::BOOL_ is;
if (!::boost::detail::winapi::IsProcessInJob(proc, _job_object, &is))
::boost::winapi::BOOL_ is;
if (!::boost::winapi::IsProcessInJob(proc, _job_object, &is))
throw_last_error();
return is!=0;
}
bool has(handle_t proc, std::error_code & ec) noexcept
{
::boost::detail::winapi::BOOL_ is;
if (!::boost::detail::winapi::IsProcessInJob(proc, _job_object, &is))
::boost::winapi::BOOL_ is;
if (!::boost::winapi::IsProcessInJob(proc, _job_object, &is))
ec = get_last_error();
return is!=0;
}
@@ -162,13 +183,13 @@ struct group_handle
inline void terminate(const group_handle &p)
{
if (!::boost::detail::winapi::TerminateJobObject(p.handle(), EXIT_FAILURE))
if (!::boost::winapi::TerminateJobObject(p.handle(), EXIT_FAILURE))
boost::process::detail::throw_last_error("TerminateJobObject() failed");
}
inline void terminate(const group_handle &p, std::error_code &ec) noexcept
{
if (!::boost::detail::winapi::TerminateJobObject(p.handle(), EXIT_FAILURE))
if (!::boost::winapi::TerminateJobObject(p.handle(), EXIT_FAILURE))
ec = boost::process::detail::get_last_error();
else
ec.clear();
@@ -176,8 +197,8 @@ inline void terminate(const group_handle &p, std::error_code &ec) noexcept
inline bool in_group()
{
::boost::detail::winapi::BOOL_ res;
if (!::boost::detail::winapi::IsProcessInJob(boost::detail::winapi::GetCurrentProcess(), nullptr, &res))
::boost::winapi::BOOL_ res;
if (!::boost::winapi::IsProcessInJob(boost::winapi::GetCurrentProcess(), nullptr, &res))
throw_last_error("IsProcessInJob failed");
return res!=0;

View File

@@ -8,7 +8,7 @@
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/windows/group_handle.hpp>
#include <boost/detail/winapi/process.hpp>
#include <boost/winapi/process.hpp>
#include <boost/process/detail/windows/handler.hpp>
namespace boost { namespace process {
@@ -19,7 +19,7 @@ namespace detail { namespace windows {
struct group_ref : handler_base_ext
{
::boost::detail::winapi::HANDLE_ handle;
::boost::winapi::HANDLE_ handle;
explicit group_ref(group_handle &g) :
handle(g.handle())
@@ -30,14 +30,14 @@ struct group_ref : handler_base_ext
{
//I can only enable this if the current process supports breakaways.
if (in_group() && break_away_enabled(nullptr))
exec.creation_flags |= boost::detail::winapi::CREATE_BREAKAWAY_FROM_JOB_;
exec.creation_flags |= boost::winapi::CREATE_BREAKAWAY_FROM_JOB_;
}
template <class Executor>
void on_success(Executor& exec) const
{
if (!::boost::detail::winapi::AssignProcessToJobObject(handle, exec.proc_info.hProcess))
if (!::boost::winapi::AssignProcessToJobObject(handle, exec.proc_info.hProcess))
exec.set_error(::boost::process::detail::get_last_error(),
"AssignProcessToJobObject() failed.");

View File

@@ -3,15 +3,15 @@
// 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_WINDOWS_IO_SERVICE_REF_HPP_
#define BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_
#ifndef BOOST_PROCESS_WINDOWS_IO_CONTEXT_REF_HPP_
#define BOOST_PROCESS_WINDOWS_IO_CONTEXT_REF_HPP_
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/async_handler.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/windows/object_handle.hpp>
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/algorithm/transformation/filter_if.hpp>
@@ -70,14 +70,14 @@ struct async_handler_collector
};
//Also set's up waiting for the exit, so it can close async stuff.
struct io_service_ref : boost::process::detail::handler_base
struct io_context_ref : boost::process::detail::handler_base
{
io_service_ref(boost::asio::io_service & ios)
io_context_ref(boost::asio::io_context & ios)
: ios(ios)
{
}
boost::asio::io_service &get() {return ios;};
boost::asio::io_context &get() {return ios;};
template <class Executor>
void on_success(Executor& exec) const
@@ -93,16 +93,16 @@ struct io_service_ref : boost::process::detail::handler_base
return;
}
::boost::detail::winapi::PROCESS_INFORMATION_ & proc = exec.proc_info;
auto this_proc = ::boost::detail::winapi::GetCurrentProcess();
::boost::winapi::PROCESS_INFORMATION_ & proc = exec.proc_info;
auto this_proc = ::boost::winapi::GetCurrentProcess();
auto proc_in = proc.hProcess;;
::boost::detail::winapi::HANDLE_ process_handle;
::boost::winapi::HANDLE_ process_handle;
if (!::boost::detail::winapi::DuplicateHandle(
if (!::boost::winapi::DuplicateHandle(
this_proc, proc_in, this_proc, &process_handle, 0,
static_cast<::boost::detail::winapi::BOOL_>(true),
::boost::detail::winapi::DUPLICATE_SAME_ACCESS_))
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
exec.set_error(::boost::process::detail::get_last_error(),
"Duplicate Pipe Failed");
@@ -127,10 +127,10 @@ struct io_service_ref : boost::process::detail::handler_base
wait_handler(const wait_handler & ) = delete;
wait_handler(wait_handler && ) = default;
wait_handler(std::vector<std::function<void(int, const std::error_code & ec)>> && funcs,
boost::asio::io_service & ios, void * handle,
boost::asio::io_context & ios, void * handle,
const std::shared_ptr<std::atomic<int>> &exit_status)
: funcs(std::move(funcs)),
handle(new boost::asio::windows::object_handle(ios, handle)),
handle(new boost::asio::windows::object_handle(ios.get_executor(), handle)),
exit_status(exit_status)
{
@@ -141,8 +141,8 @@ struct io_service_ref : boost::process::detail::handler_base
if (ec_in)
ec = std::error_code(ec_in.value(), std::system_category());
::boost::detail::winapi::DWORD_ code;
::boost::detail::winapi::GetExitCodeProcess(handle->native(), &code);
::boost::winapi::DWORD_ code;
::boost::winapi::GetExitCodeProcess(handle->native_handle(), &code);
exit_status->store(code);
for (auto & func : funcs)
@@ -152,9 +152,9 @@ struct io_service_ref : boost::process::detail::handler_base
};
private:
boost::asio::io_service &ios;
boost::asio::io_context &ios;
};
}}}}
#endif /* BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_ */
#endif /* BOOST_PROCESS_WINDOWS_IO_CONTEXT_REF_HPP_ */

View File

@@ -9,36 +9,20 @@
#include <boost/process/detail/config.hpp>
#include <system_error>
#include <cstdlib>
#include <boost/detail/winapi/process.hpp>
#include <boost/winapi/process.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
constexpr static ::boost::detail::winapi::DWORD_ still_active = 259;
constexpr static ::boost::winapi::DWORD_ still_active = 259;
struct child_handle;
inline bool is_running(const child_handle &p, int & exit_code)
{
::boost::detail::winapi::DWORD_ code;
//single value, not needed in the winapi.
if (!::boost::detail::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::detail::winapi::DWORD_ code;
::boost::winapi::DWORD_ code;
//single value, not needed in the winapi.
if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &code))
if (!::boost::winapi::GetExitCodeProcess(p.process_handle(), &code))
ec = ::boost::process::detail::get_last_error();
else
ec.clear();
@@ -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)

View File

@@ -6,71 +6,187 @@
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_JOB_WORKAROUND_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_JOB_WORKAROUND_HPP_
#include <boost/detail/winapi/config.hpp>
#include <boost/detail/winapi/basic_types.hpp>
#include <boost/detail/winapi/dll.hpp>
#include <boost/winapi/config.hpp>
#include <boost/winapi/basic_types.hpp>
#include <boost/winapi/dll.hpp>
#include <boost/winapi/overlapped.hpp>
#if defined( BOOST_USE_WINDOWS_H )
#include <windows.h>
#else
extern "C"
{
BOOST_SYMBOL_IMPORT ::boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC CreateIoCompletionPort(
::boost::winapi::HANDLE_ FileHandle,
::boost::winapi::HANDLE_ ExistingCompletionPort,
::boost::winapi::ULONG_PTR_ CompletionKey,
::boost::winapi::DWORD_ NumberOfConcurrentThreads
);
BOOST_SYMBOL_IMPORT ::boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC GetQueuedCompletionStatus(
::boost::winapi::HANDLE_ CompletionPort,
::boost::winapi::LPDWORD_ lpNumberOfBytes,
::boost::winapi::ULONG_PTR_ *lpCompletionKey,
_OVERLAPPED **lpOverlapped,
::boost::winapi::DWORD_ dwMilliseconds
);
}
#endif
namespace boost { namespace process { namespace detail { namespace windows { namespace workaround {
extern "C"
{
struct JOBOBJECT_ASSOCIATE_COMPLETION_PORT_
{
::boost::winapi::PVOID_ CompletionKey;
::boost::winapi::HANDLE_ CompletionPort;
};
constexpr static int JOB_OBJECT_MSG_END_OF_JOB_TIME_ = 1;
constexpr static int JOB_OBJECT_MSG_END_OF_PROCESS_TIME_ = 2;
constexpr static int JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT_ = 3;
constexpr static int JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO_ = 4;
constexpr static int JOB_OBJECT_MSG_NEW_PROCESS_ = 6;
constexpr static int JOB_OBJECT_MSG_EXIT_PROCESS_ = 7;
constexpr static int JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS_ = 8;
constexpr static int JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT_ = 9;
constexpr static int JOB_OBJECT_MSG_JOB_MEMORY_LIMIT_ = 10;
constexpr static int JOB_OBJECT_MSG_NOTIFICATION_LIMIT_ = 11;
constexpr static int JOB_OBJECT_MSG_JOB_CYCLE_TIME_LIMIT_ = 12;
constexpr static int JOB_OBJECT_MSG_SILO_TERMINATED_ = 13;
}
BOOST_FORCEINLINE ::boost::winapi::BOOL_ get_queued_completion_status(
::boost::winapi::HANDLE_ CompletionPort,
::boost::winapi::LPDWORD_ lpNumberOfBytes,
::boost::winapi::ULONG_PTR_ *lpCompletionKey,
::boost::winapi::LPOVERLAPPED_ *lpOverlapped,
::boost::winapi::DWORD_ dwMilliseconds)
{
return ::GetQueuedCompletionStatus(
CompletionPort,
lpNumberOfBytes,
lpCompletionKey,
reinterpret_cast<::_OVERLAPPED**>(lpOverlapped),
dwMilliseconds);
}
#if defined( BOOST_USE_WINDOWS_H )
constexpr auto static JobObjectExtendedLimitInformation_ = ::JobObjectExtendedLimitInformation;
constexpr auto static JobObjectAssociateCompletionPortInformation_ = ::JobObjectAssociateCompletionPortInformation;
constexpr auto static JobObjectBasicAccountingInformation_ = ::JobObjectBasicAccountingInformation;
using JOBOBJECT_BASIC_LIMIT_INFORMATION_ = ::JOBOBJECT_BASIC_LIMIT_INFORMATION;
using JOBOBJECTINFOCLASS_ = ::JOBOBJECTINFOCLASS;
using IO_COUNTERS_ = ::IO_COUNTERS;
using JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ = ::JOBOBJECT_EXTENDED_LIMIT_INFORMATION;
using JOBOBJECT_BASIC_ACCOUNTING_INFORMATION_ = ::JOBOBJECT_BASIC_ACCOUNTING_INFORMATION;
inline ::boost::winapi::BOOL_ query_information_job_object(
::boost::winapi::HANDLE_ hJob,
JOBOBJECTINFOCLASS_ JobObjectInfoClass,
void * lpJobObjectInfo,
::boost::winapi::DWORD_ cbJobObjectInfoLength,
::boost::winapi::DWORD_ *lpReturnLength)
{
return ::QueryInformationJobObject(hJob, JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength, lpReturnLength);
}
inline ::boost::winapi::BOOL_ set_information_job_object(
::boost::winapi::HANDLE_ hJob,
JOBOBJECTINFOCLASS_ JobObjectInfoClass,
void * lpJobObjectInfo,
::boost::winapi::DWORD_ cbJobObjectInfoLength)
{
return ::SetInformationJobObject(hJob, JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength);
}
#else
//this import workaround is to keep it a header-only library. and enums cannot be imported from the winapi.
extern "C"
{
typedef enum _JOBOBJECTINFOCLASS_ {
JobObjectBasicAccountingInformation_ = 1, JobObjectBasicLimitInformation_,
JobObjectBasicProcessIdList_, JobObjectBasicUIRestrictions_,
JobObjectSecurityLimitInformation_, JobObjectEndOfJobTimeInformation_,
JobObjectAssociateCompletionPortInformation_, JobObjectBasicAndIoAccountingInformation_,
JobObjectExtendedLimitInformation_, JobObjectJobSetInformation_,
JobObjectGroupInformation_,
JobObjectNotificationLimitInformation_,
JobObjectLimitViolationInformation_,
JobObjectGroupInformationEx_,
JobObjectCpuRateControlInformation_,
JobObjectCompletionFilter_,
JobObjectCompletionCounter_,
JobObjectReserved1Information_ = 18,
JobObjectReserved2Information_,
JobObjectReserved3Information_,
JobObjectReserved4Information_,
JobObjectReserved5Information_,
JobObjectReserved6Information_,
JobObjectReserved7Information_,
JobObjectReserved8Information_,
MaxJobObjectInfoClass_
} JOBOBJECTINFOCLASS_;
typedef enum _JOBOBJECTINFOCLASS_
{
JobObjectBasicAccountingInformation_ = 1,
JobObjectBasicLimitInformation_,
JobObjectBasicProcessIdList_,
JobObjectBasicUIRestrictions_,
JobObjectSecurityLimitInformation_,
JobObjectEndOfJobTimeInformation_,
JobObjectAssociateCompletionPortInformation_,
JobObjectBasicAndIoAccountingInformation_,
JobObjectExtendedLimitInformation_,
JobObjectJobSetInformation_,
JobObjectGroupInformation_,
JobObjectNotificationLimitInformation_,
JobObjectLimitViolationInformation_,
JobObjectGroupInformationEx_,
JobObjectCpuRateControlInformation_,
JobObjectCompletionFilter_,
JobObjectCompletionCounter_,
JobObjectReserved1Information_ = 18,
JobObjectReserved2Information_,
JobObjectReserved3Information_,
JobObjectReserved4Information_,
JobObjectReserved5Information_,
JobObjectReserved6Information_,
JobObjectReserved7Information_,
JobObjectReserved8Information_,
MaxJobObjectInfoClass_
} JOBOBJECTINFOCLASS_;
typedef struct _JOBOBJECT_BASIC_LIMIT_INFORMATION_ {
::boost::detail::winapi::LARGE_INTEGER_ PerProcessUserTimeLimit;
::boost::detail::winapi::LARGE_INTEGER_ PerJobUserTimeLimit;
::boost::detail::winapi::DWORD_ LimitFlags;
::boost::detail::winapi::SIZE_T_ MinimumWorkingSetSize;
::boost::detail::winapi::SIZE_T_ MaximumWorkingSetSize;
::boost::detail::winapi::DWORD_ ActiveProcessLimit;
::boost::detail::winapi::ULONG_PTR_ Affinity;
::boost::detail::winapi::DWORD_ PriorityClass;
::boost::detail::winapi::DWORD_ SchedulingClass;
typedef struct _JOBOBJECT_BASIC_LIMIT_INFORMATION_
{
::boost::winapi::LARGE_INTEGER_ PerProcessUserTimeLimit;
::boost::winapi::LARGE_INTEGER_ PerJobUserTimeLimit;
::boost::winapi::DWORD_ LimitFlags;
::boost::winapi::SIZE_T_ MinimumWorkingSetSize;
::boost::winapi::SIZE_T_ MaximumWorkingSetSize;
::boost::winapi::DWORD_ ActiveProcessLimit;
::boost::winapi::ULONG_PTR_ Affinity;
::boost::winapi::DWORD_ PriorityClass;
::boost::winapi::DWORD_ SchedulingClass;
} JOBOBJECT_BASIC_LIMIT_INFORMATION_;
typedef struct _IO_COUNTERS_ {
::boost::detail::winapi::ULONGLONG_ ReadOperationCount;
::boost::detail::winapi::ULONGLONG_ WriteOperationCount;
::boost::detail::winapi::ULONGLONG_ OtherOperationCount;
::boost::detail::winapi::ULONGLONG_ ReadTransferCount;
::boost::detail::winapi::ULONGLONG_ WriteTransferCount;
::boost::detail::winapi::ULONGLONG_ OtherTransferCount;
typedef struct _JOBOBJECT_BASIC_ACCOUNTING_INFORMATION_ {
::boost::winapi::LARGE_INTEGER_ TotalUserTime;
::boost::winapi::LARGE_INTEGER_ TotalKernelTime;
::boost::winapi::LARGE_INTEGER_ ThisPeriodTotalUserTime;
::boost::winapi::LARGE_INTEGER_ ThisPeriodTotalKernelTime;
::boost::winapi::DWORD_ TotalPageFaultCount;
::boost::winapi::DWORD_ TotalProcesses;
::boost::winapi::DWORD_ ActiveProcesses;
::boost::winapi::DWORD_ TotalTerminatedProcesses;
} JOBOBJECT_BASIC_ACCOUNTING_INFORMATION_;
typedef struct _IO_COUNTERS_
{
::boost::winapi::ULONGLONG_ ReadOperationCount;
::boost::winapi::ULONGLONG_ WriteOperationCount;
::boost::winapi::ULONGLONG_ OtherOperationCount;
::boost::winapi::ULONGLONG_ ReadTransferCount;
::boost::winapi::ULONGLONG_ WriteTransferCount;
::boost::winapi::ULONGLONG_ OtherTransferCount;
} IO_COUNTERS_;
typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ {
JOBOBJECT_BASIC_LIMIT_INFORMATION_ BasicLimitInformation;
IO_COUNTERS_ IoInfo;
::boost::detail::winapi::SIZE_T_ ProcessMemoryLimit;
::boost::detail::winapi::SIZE_T_ JobMemoryLimit;
::boost::detail::winapi::SIZE_T_ PeakProcessMemoryUsed;
::boost::detail::winapi::SIZE_T_ PeakJobMemoryUsed;
typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION_
{
JOBOBJECT_BASIC_LIMIT_INFORMATION_ BasicLimitInformation;
IO_COUNTERS_ IoInfo;
::boost::winapi::SIZE_T_ ProcessMemoryLimit;
::boost::winapi::SIZE_T_ JobMemoryLimit;
::boost::winapi::SIZE_T_ PeakProcessMemoryUsed;
::boost::winapi::SIZE_T_ PeakJobMemoryUsed;
} JOBOBJECT_EXTENDED_LIMIT_INFORMATION_;
@@ -82,25 +198,28 @@ typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ {
_Out_opt_ LPDWORD lpReturnLength
);
*/
typedef ::boost::detail::winapi::BOOL_ ( WINAPI *query_information_job_object_p)(
::boost::detail::winapi::HANDLE_,
typedef ::boost::winapi::BOOL_ (BOOST_WINAPI_WINAPI_CC *query_information_job_object_p)(
::boost::winapi::HANDLE_,
JOBOBJECTINFOCLASS_,
void *,
::boost::detail::winapi::DWORD_,
::boost::detail::winapi::DWORD_ *);
::boost::winapi::DWORD_,
::boost::winapi::DWORD_ *);
inline ::boost::detail::winapi::BOOL_ WINAPI query_information_job_object(
::boost::detail::winapi::HANDLE_ hJob,
inline ::boost::winapi::BOOL_ query_information_job_object(
::boost::winapi::HANDLE_ hJob,
JOBOBJECTINFOCLASS_ JobObjectInfoClass,
void * lpJobObjectInfo,
::boost::detail::winapi::DWORD_ cbJobObjectInfoLength,
::boost::detail::winapi::DWORD_ *lpReturnLength)
void *lpJobObjectInfo,
::boost::winapi::DWORD_ cbJobObjectInfoLength,
::boost::winapi::DWORD_ *lpReturnLength)
{
static ::boost::detail::winapi::HMODULE_ h = ::boost::detail::winapi::get_module_handle("Kernel32.dll");
static query_information_job_object_p f = reinterpret_cast<query_information_job_object_p>(::boost::detail::winapi::get_proc_address(h, "QueryInformationJobObject"));
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);
return (*f)(hJob, JobObjectInfoClass, lpJobObjectInfo,
cbJobObjectInfoLength, lpReturnLength);
}
/*BOOL WINAPI SetInformationJobObject(
@@ -110,30 +229,33 @@ inline ::boost::detail::winapi::BOOL_ WINAPI query_information_job_object(
_In_ DWORD cbJobObjectInfoLength
);*/
typedef ::boost::detail::winapi::BOOL_ ( WINAPI *set_information_job_object_p)(
::boost::detail::winapi::HANDLE_,
typedef ::boost::winapi::BOOL_ (BOOST_WINAPI_WINAPI_CC *set_information_job_object_p)(
::boost::winapi::HANDLE_,
JOBOBJECTINFOCLASS_,
void *,
::boost::detail::winapi::DWORD_);
::boost::winapi::DWORD_);
}
inline ::boost::detail::winapi::BOOL_ WINAPI set_information_job_object(
::boost::detail::winapi::HANDLE_ hJob,
inline ::boost::winapi::BOOL_ set_information_job_object(
::boost::winapi::HANDLE_ hJob,
JOBOBJECTINFOCLASS_ JobObjectInfoClass,
void * lpJobObjectInfo,
::boost::detail::winapi::DWORD_ cbJobObjectInfoLength)
void *lpJobObjectInfo,
::boost::winapi::DWORD_ cbJobObjectInfoLength)
{
static ::boost::detail::winapi::HMODULE_ h = ::boost::detail::winapi::get_module_handle("Kernel32.dll");
static set_information_job_object_p f = reinterpret_cast<set_information_job_object_p>(::boost::detail::winapi::get_proc_address(h, "SetInformationJobObject"));
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);
return (*f)(hJob, JobObjectInfoClass, lpJobObjectInfo,
cbJobObjectInfoLength);
}
constexpr static ::boost::detail::winapi::DWORD_ JOB_OBJECT_LIMIT_BREAKAWAY_OK_ = 0x00000800;
#endif
constexpr static ::boost::winapi::DWORD_ JOB_OBJECT_LIMIT_BREAKAWAY_OK_ = 0x00000800;
}}}}}
#endif /* BOOST_PROCESS_DETAIL_WINDOWS_JOB_WORKAROUND_HPP_ */

View File

@@ -9,8 +9,8 @@
#include <locale>
#include <boost/core/ignore_unused.hpp>
#include <boost/detail/winapi/file_management.hpp>
#include <boost/detail/winapi/character_code_conversion.hpp>
#include <boost/winapi/file_management.hpp>
#include <boost/winapi/character_code_conversion.hpp>
namespace boost
{
@@ -41,13 +41,17 @@ class windows_file_codecvt
wchar_t* to, wchar_t* to_end, wchar_t*& to_next) const override
{
boost::ignore_unused(state);
::boost::detail::winapi::UINT_ codepage = AreFileApisANSI() ?
::boost::detail::winapi::CP_ACP_ :
::boost::detail::winapi::CP_OEMCP_;
int count;
if ((count = ::boost::detail::winapi::MultiByteToWideChar(codepage,
::boost::detail::winapi::MB_PRECOMPOSED_, from,
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)
{
return error; // conversion failed
@@ -64,13 +68,17 @@ class windows_file_codecvt
char* to, char* to_end, char*& to_next) const override
{
boost::ignore_unused(state);
auto codepage = ::boost::detail::winapi::AreFileApisANSI() ?
::boost::detail::winapi::CP_ACP_ :
::boost::detail::winapi::CP_OEMCP_;
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::detail::winapi::WideCharToMultiByte(codepage,
::boost::detail::winapi::WC_NO_BEST_FIT_CHARS_, from,
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)
{
return error; // conversion failed

View File

@@ -10,9 +10,9 @@
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_NULL_IN_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_NULL_IN_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/handle_info.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/handle_info.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/file_descriptor.hpp>
@@ -26,12 +26,12 @@ public:
template <class WindowsExecutor>
void on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(source.handle(),
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
boost::winapi::SetHandleInformation(source.handle(),
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdInput = source.handle();
e.startup_info.dwFlags |= boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.dwFlags |= boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
};

View File

@@ -10,9 +10,9 @@
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_NULL_OUT_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_NULL_OUT_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/detail/winapi/handle_info.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/handle_info.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/file_descriptor.hpp>
@@ -31,12 +31,12 @@ template<>
template<typename WindowsExecutor>
void null_out<1,-1>::on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(sink.handle(),
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
boost::winapi::SetHandleInformation(sink.handle(),
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdOutput = sink.handle();
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
@@ -45,12 +45,12 @@ template<>
template<typename WindowsExecutor>
void null_out<2,-1>::on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(sink.handle(),
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
boost::winapi::SetHandleInformation(sink.handle(),
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdError = sink.handle();
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
@@ -59,13 +59,13 @@ template<>
template<typename WindowsExecutor>
void null_out<1,2>::on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(sink.handle(),
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
boost::winapi::SetHandleInformation(sink.handle(),
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdOutput = sink.handle();
e.startup_info.hStdError = sink.handle();
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}

View File

@@ -9,7 +9,6 @@
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/async_handler.hpp>
#include <boost/detail/winapi/process.hpp>
#include <system_error>
#include <functional>
@@ -26,10 +25,10 @@ struct on_exit_ : boost::process::detail::windows::async_handler
template<typename Executor>
std::function<void(int, const std::error_code&)> on_exit_handler(Executor&)
{
auto handler = this->handler;
return [handler](int exit_code, const std::error_code & ec)
auto handler_ = this->handler;
return [handler_](int exit_code, const std::error_code & ec)
{
handler(static_cast<int>(exit_code), ec);
handler_(static_cast<int>(exit_code), ec);
};
}

View File

@@ -10,45 +10,45 @@
#ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_PIPE_IN_HPP
#define BOOST_PROCESS_WINDOWS_INITIALIZERS_PIPE_IN_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/process/detail/handler_base.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
struct pipe_in : public ::boost::process::detail::handler_base
{
::boost::detail::winapi::HANDLE_ handle;
::boost::winapi::HANDLE_ handle;
pipe_in(::boost::detail::winapi::HANDLE_ handle) : handle(handle) {}
pipe_in(::boost::winapi::HANDLE_ handle) : handle(handle) {}
template<typename T> //async_pipe
pipe_in(T & p) : handle(p.native_source())
{
p.assign_source(::boost::detail::winapi::INVALID_HANDLE_VALUE_);
p.assign_source(::boost::winapi::INVALID_HANDLE_VALUE_);
}
template <class WindowsExecutor>
void on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdInput = handle;
e.startup_info.dwFlags |= boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.dwFlags |= boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
template<typename WindowsExecutor>
void on_error(WindowsExecutor &, const std::error_code &) const
{
::boost::detail::winapi::CloseHandle(handle);
::boost::winapi::CloseHandle(handle);
}
template<typename WindowsExecutor>
void on_success(WindowsExecutor &) const
{
::boost::detail::winapi::CloseHandle(handle);
::boost::winapi::CloseHandle(handle);
}
};

View File

@@ -11,8 +11,8 @@
#ifndef BOOST_PROCESS_WINDOWS_PIPE_OUT_HPP
#define BOOST_PROCESS_WINDOWS_PIPE_OUT_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/handles.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/process/detail/handler_base.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
@@ -22,13 +22,13 @@ namespace boost { namespace process { namespace detail { namespace windows {
template<int p1, int p2>
struct pipe_out : public ::boost::process::detail::handler_base
{
::boost::detail::winapi::HANDLE_ handle;
::boost::winapi::HANDLE_ handle;
pipe_out(::boost::detail::winapi::HANDLE_ handle) : handle(handle) {}
pipe_out(::boost::winapi::HANDLE_ handle) : handle(handle) {}
template<typename T>
pipe_out(T & p) : handle(p.native_sink())
{
p.assign_sink(::boost::detail::winapi::INVALID_HANDLE_VALUE_);
p.assign_sink(::boost::winapi::INVALID_HANDLE_VALUE_);
}
template<typename WindowsExecutor>
@@ -37,13 +37,13 @@ struct pipe_out : public ::boost::process::detail::handler_base
template<typename WindowsExecutor>
void on_error(WindowsExecutor &, const std::error_code &) const
{
::boost::detail::winapi::CloseHandle(handle);
::boost::winapi::CloseHandle(handle);
}
template<typename WindowsExecutor>
void on_success(WindowsExecutor &) const
{
::boost::detail::winapi::CloseHandle(handle);
::boost::winapi::CloseHandle(handle);
}
};
@@ -51,12 +51,12 @@ template<>
template<typename WindowsExecutor>
void pipe_out<1,-1>::on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdOutput = handle;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
@@ -64,13 +64,13 @@ template<>
template<typename WindowsExecutor>
void pipe_out<2,-1>::on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdError = handle;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}
@@ -78,13 +78,13 @@ template<>
template<typename WindowsExecutor>
void pipe_out<1,2>::on_setup(WindowsExecutor &e) const
{
boost::detail::winapi::SetHandleInformation(handle,
boost::detail::winapi::HANDLE_FLAG_INHERIT_,
boost::detail::winapi::HANDLE_FLAG_INHERIT_);
boost::winapi::SetHandleInformation(handle,
boost::winapi::HANDLE_FLAG_INHERIT_,
boost::winapi::HANDLE_FLAG_INHERIT_);
e.startup_info.hStdOutput = handle;
e.startup_info.hStdError = handle;
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
e.inherit_handles = true;
}

View File

@@ -19,9 +19,8 @@
#include <array>
#include <atomic>
#include <cstdlib>
#include <boost/detail/winapi/shell.hpp>
#include <boost/winapi/shell.hpp>
#include <boost/process/environment.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
@@ -29,20 +28,46 @@ inline boost::filesystem::path search_path(
const boost::filesystem::path &filename,
const std::vector<boost::filesystem::path> &path)
{
for (const boost::filesystem::path & pp : path)
const ::boost::process::wnative_environment ne{};
typedef typename ::boost::process::wnative_environment::const_entry_type value_type;
const auto id = L"PATHEXT";
auto itr = std::find_if(ne.cbegin(), ne.cend(),
[&](const value_type & e)
{return id == ::boost::to_upper_copy(e.get_name(), ::boost::process::detail::process_locale());});
auto extensions_in = itr->to_vector();
std::vector<std::wstring> extensions((extensions_in.size() * 2) + 1);
auto it_ex = extensions.begin();
it_ex++;
it_ex = std::transform(extensions_in.begin(), extensions_in.end(), it_ex,
[](const std::wstring & ws){return boost::to_lower_copy(ws, ::boost::process::detail::process_locale());});
std::transform(extensions_in.begin(), extensions_in.end(), it_ex,
[](const std::wstring & ws){return boost::to_upper_copy(ws, ::boost::process::detail::process_locale());});
std::copy(std::make_move_iterator(extensions_in.begin()), std::make_move_iterator(extensions_in.end()), extensions.begin() + 1);
for (auto & ext : extensions)
boost::to_lower(ext);
for (const boost::filesystem::path & pp_ : path)
{
auto full = pp / filename;
std::array<std::string, 4> extensions {{ "", ".exe", ".com", ".bat" }};
auto p = pp_ / filename;
for (boost::filesystem::path ext : extensions)
{
auto p = full;
p += ext;
boost::filesystem::path pp = p;
pp += ext;
boost::system::error_code ec;
bool file = boost::filesystem::is_regular_file(p, ec);
bool file = boost::filesystem::is_regular_file(pp, ec);
if (!ec && file &&
::boost::detail::winapi::sh_get_file_info(p.string().c_str(), 0, 0, 0, ::boost::detail::winapi::SHGFI_EXETYPE_))
::boost::winapi::sh_get_file_info(pp.native().c_str(), 0, 0, 0, ::boost::winapi::SHGFI_EXETYPE_))
{
return p;
return pp;
}
}
}

View File

@@ -13,15 +13,15 @@
#include <boost/process/detail/config.hpp>
#include <system_error>
#include <boost/filesystem/path.hpp>
#include <boost/detail/winapi/basic_types.hpp>
#include <boost/detail/winapi/get_system_directory.hpp>
#include <boost/winapi/basic_types.hpp>
#include <boost/winapi/get_system_directory.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
inline boost::filesystem::path shell_path()
{
::boost::detail::winapi::WCHAR_ sysdir[260];
unsigned int size = ::boost::detail::winapi::get_system_directory(sysdir, sizeof(sysdir));
::boost::winapi::WCHAR_ sysdir[260];
unsigned int size = ::boost::winapi::get_system_directory(sysdir, sizeof(sysdir));
if (!size)
throw_last_error("GetSystemDirectory() failed");
@@ -32,12 +32,12 @@ inline boost::filesystem::path shell_path()
inline boost::filesystem::path shell_path(std::error_code &ec) noexcept
{
::boost::detail::winapi::WCHAR_ sysdir[260];
unsigned int size = ::boost::detail::winapi::get_system_directory(sysdir, sizeof(sysdir));
::boost::winapi::WCHAR_ sysdir[260];
unsigned int size = ::boost::winapi::get_system_directory(sysdir, sizeof(sysdir));
boost::filesystem::path p;
if (!size)
ec = std::error_code(
::boost::detail::winapi::GetLastError(),
::boost::winapi::GetLastError(),
std::system_category());
else
{

View File

@@ -11,26 +11,32 @@
#ifndef BOOST_PROCESS_WINDOWS_SHOW_WINDOW_HPP
#define BOOST_PROCESS_WINDOWS_SHOW_WINDOW_HPP
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/show_window.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/show_window.hpp>
#include <boost/process/detail/handler_base.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
template<::boost::detail::winapi::WORD_ Flags>
template<::boost::winapi::WORD_ Flags>
struct show_window : ::boost::process::detail::handler_base
{
template <class WindowsExecutor>
void on_setup(WindowsExecutor &e) const
{
e.startup_info.dwFlags |= ::boost::detail::winapi::STARTF_USESHOWWINDOW_;
e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESHOWWINDOW_;
e.startup_info.wShowWindow |= Flags;
}
};
struct create_no_window_ : public ::boost::process::detail::handler_base
{
template <class Executor>
void on_setup(Executor &exec) const
{
exec.creation_flags |= ::boost::winapi::CREATE_NO_WINDOW_;
}
};
}}}}

View File

@@ -13,36 +13,31 @@
#include <boost/process/detail/config.hpp>
#include <system_error>
#include <cstdlib>
#include <boost/detail/winapi/process.hpp>
#include <boost/detail/winapi/get_last_error.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/get_last_error.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
struct child_handle;
inline void terminate(child_handle &p)
{
if (!::boost::detail::winapi::TerminateProcess(p.process_handle(), EXIT_FAILURE))
boost::process::detail::throw_last_error("TerminateProcess() failed");
::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
}
inline void terminate(child_handle &p, std::error_code &ec) noexcept
{
if (!::boost::detail::winapi::TerminateProcess(p.process_handle(), EXIT_FAILURE))
if (!::boost::winapi::TerminateProcess(p.process_handle(), EXIT_FAILURE))
ec = boost::process::detail::get_last_error();
else
{
ec.clear();
::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
::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;
terminate(p, ec);
boost::process::detail::throw_error(ec, "TerminateProcess() failed in terminate");
}
}}}}

View File

@@ -13,147 +13,41 @@
#include <boost/process/detail/config.hpp>
#include <system_error>
#include <boost/detail/winapi/synchronization.hpp>
#include <boost/detail/winapi/process.hpp>
#include <boost/winapi/synchronization.hpp>
#include <boost/winapi/process.hpp>
#include <boost/process/detail/windows/child_handle.hpp>
#include <chrono>
namespace boost { namespace process { namespace detail { namespace windows {
inline void wait(child_handle &p, int & exit_code)
{
if (::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
::boost::detail::winapi::infinite) == ::boost::detail::winapi::wait_failed)
throw_last_error("WaitForSingleObject() failed");
::boost::detail::winapi::DWORD_ _exit_code;
if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
throw_last_error("GetExitCodeProcess() failed");
::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::detail::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::detail::winapi::DWORD_ _exit_code = 1;
::boost::winapi::DWORD_ _exit_code = 1;
if (::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
::boost::detail::winapi::infinite) == ::boost::detail::winapi::wait_failed)
if (::boost::winapi::WaitForSingleObject(p.process_handle(),
::boost::winapi::infinite) == ::boost::winapi::wait_failed)
ec = std::error_code(
::boost::detail::winapi::GetLastError(),
::boost::winapi::GetLastError(),
std::system_category());
else if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
else if (!::boost::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
ec = std::error_code(
::boost::detail::winapi::GetLastError(),
::boost::winapi::GetLastError(),
std::system_category());
else
ec.clear();
::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
::boost::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::winapi::INVALID_HANDLE_VALUE_;
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::detail::winapi::DWORD_ wait_code;
wait_code = ::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
static_cast<::boost::detail::winapi::DWORD_>(ms.count()));
if (wait_code == ::boost::detail::winapi::wait_failed)
throw_last_error("WaitForSingleObject() failed");
else if (wait_code == ::boost::detail::winapi::wait_timeout)
return false; //
::boost::detail::winapi::DWORD_ _exit_code;
if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
throw_last_error("GetExitCodeProcess() failed");
exit_code = static_cast<int>(_exit_code);
::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::detail::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(
child_handle &p,
int & exit_code,
const std::chrono::duration<Rep, Period>& rel_time,
std::error_code &ec) noexcept
{
std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(rel_time);
::boost::detail::winapi::DWORD_ wait_code;
wait_code = ::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
static_cast<::boost::detail::winapi::DWORD_>(ms.count()));
if (wait_code == ::boost::detail::winapi::wait_failed)
ec = std::error_code(
::boost::detail::winapi::GetLastError(),
std::system_category());
else if (wait_code == ::boost::detail::winapi::wait_timeout)
return false; //
::boost::detail::winapi::DWORD_ _exit_code = 1;
if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
{
ec = std::error_code(
::boost::detail::winapi::GetLastError(),
std::system_category());
return false;
}
else
ec.clear();
exit_code = static_cast<int>(_exit_code);
::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
return true;
;
}
template< class Clock, class Duration >
inline bool wait_until(
child_handle &p,
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::detail::winapi::DWORD_ wait_code;
wait_code = ::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
static_cast<::boost::detail::winapi::DWORD_>(ms.count()));
if (wait_code == ::boost::detail::winapi::wait_failed)
throw_last_error("WaitForSingleObject() failed");
else if (wait_code == ::boost::detail::winapi::wait_timeout)
return false;
::boost::detail::winapi::DWORD_ _exit_code;
if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
throw_last_error("GetExitCodeProcess() failed");
exit_code = static_cast<int>(_exit_code);
::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
return true;
}
template< class Clock, class Duration >
inline bool wait_until(
child_handle &p,
@@ -163,30 +57,66 @@ inline bool wait_until(
{
std::chrono::milliseconds ms =
std::chrono::duration_cast<std::chrono::milliseconds>(
timeout_time - std::chrono::system_clock::now());
timeout_time - Clock::now());
::boost::detail::winapi::DWORD_ _exit_code = 1;
::boost::winapi::DWORD_ wait_code;
wait_code = ::boost::winapi::WaitForSingleObject(p.process_handle(),
static_cast<::boost::winapi::DWORD_>(ms.count()));
if (::boost::detail::winapi::WaitForSingleObject(p.process_handle(),
static_cast<::boost::detail::winapi::DWORD_>(ms.count()))
== ::boost::detail::winapi::wait_failed)
if (wait_code == ::boost::winapi::wait_failed)
ec = std::error_code(
::boost::detail::winapi::GetLastError(),
::boost::winapi::GetLastError(),
std::system_category());
else if (!::boost::detail::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code))
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::detail::winapi::GetLastError(),
::boost::winapi::GetLastError(),
std::system_category());
else
ec.clear();
exit_code = static_cast<int>(exit_code);
::boost::detail::winapi::CloseHandle(p.proc_info.hProcess);
p.proc_info.hProcess = ::boost::detail::winapi::INVALID_HANDLE_VALUE_;
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;
;
}
template< class Clock, class Duration >
inline bool wait_until(
child_handle &p,
int & exit_code,
const std::chrono::time_point<Clock, Duration>& timeout_time)
{
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 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) noexcept
{
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;
}
}}}}

View File

@@ -7,92 +7,79 @@
#define BOOST_PROCESS_DETAIL_WINDOWS_WAIT_GROUP_HPP_
#include <boost/process/detail/config.hpp>
#include <boost/detail/winapi/jobs.hpp>
#include <boost/detail/winapi/wait.hpp>
#include <boost/process/detail/windows/group_handle.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::detail::winapi::WaitForSingleObject(p.handle(),
::boost::detail::winapi::infinite) == ::boost::detail::winapi::wait_failed)
throw_last_error("WaitForSingleObject() failed");
inline bool wait_impl(const group_handle & p, std::error_code & ec, std::chrono::system_clock::rep wait_time)
{
::boost::winapi::DWORD_ completion_code;
::boost::winapi::ULONG_PTR_ completion_key;
::boost::winapi::LPOVERLAPPED_ overlapped;
auto start_time = std::chrono::system_clock::now();
while (workaround::get_queued_completion_status(
p._io_port, &completion_code,
&completion_key, &overlapped, wait_time))
{
if (reinterpret_cast<::boost::winapi::HANDLE_>(completion_key) == p._job_object &&
completion_code == workaround::JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO_)
{
//double check, could be a different handle from a child
workaround::JOBOBJECT_BASIC_ACCOUNTING_INFORMATION_ info;
if (!workaround::query_information_job_object(
p._job_object,
workaround::JobObjectBasicAccountingInformation_,
static_cast<void *>(&info),
sizeof(info), nullptr))
{
ec = get_last_error();
return false;
}
else if (info.ActiveProcesses == 0)
return false; //correct, nothing left.
}
//reduce the remaining wait time -> in case interrupted by something else
if (wait_time != ::boost::winapi::infinite)
{
auto now = std::chrono::system_clock::now();
auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
wait_time -= diff.count();
start_time = now;
if (wait_time <= 0)
return true; //timeout with other source
}
}
auto ec_ = get_last_error();
if (ec_.value() == ::boost::winapi::wait_timeout)
return true; //timeout
ec = ec_;
return false;
}
inline void wait(const group_handle &p, std::error_code &ec)
{
if (::boost::detail::winapi::WaitForSingleObject(p.handle(),
::boost::detail::winapi::infinite) == ::boost::detail::winapi::wait_failed)
ec = get_last_error();
wait_impl(p, ec, ::boost::winapi::infinite);
}
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::detail::winapi::DWORD_ wait_code;
wait_code = ::boost::detail::winapi::WaitForSingleObject(p.handle(), ms.count());
if (wait_code == ::boost::detail::winapi::wait_failed)
throw_last_error("WaitForSingleObject() failed");
else if (wait_code == ::boost::detail::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(
const group_handle &p,
const std::chrono::duration<Rep, Period>& rel_time,
std::error_code &ec)
{
std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(rel_time);
::boost::detail::winapi::DWORD_ wait_code;
wait_code = ::boost::detail::winapi::WaitForSingleObject(p.handle(), ms.count());
if (wait_code == ::boost::detail::winapi::wait_failed)
ec = get_last_error();
else if (wait_code == ::boost::detail::winapi::wait_timeout)
return false; //
return true;
}
template< class Clock, class Duration >
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::detail::winapi::DWORD_ wait_code;
wait_code = ::boost::detail::winapi::WaitForSingleObject(p.handle(), ms.count());
if (wait_code == ::boost::detail::winapi::wait_failed)
throw_last_error("WaitForSingleObject() failed");
else if (wait_code == ::boost::detail::winapi::wait_timeout)
return false; //
return true;
}
template< class Clock, class Duration >
inline bool wait_until(
const group_handle &p,
@@ -101,19 +88,43 @@ inline bool wait_until(
{
std::chrono::milliseconds ms =
std::chrono::duration_cast<std::chrono::milliseconds>(
timeout_time - std::chrono::system_clock::now());
timeout_time - Clock::now());
::boost::detail::winapi::DWORD_ wait_code;
wait_code = ::boost::detail::winapi::WaitForSingleObject(p.handle(), ms.count());
auto timeout = wait_impl(p, ec, ms.count());
return !ec && !timeout;
}
if (wait_code == ::boost::detail::winapi::wait_failed)
ec = get_last_error();
template< class Clock, class Duration >
inline bool wait_until(
const group_handle &p,
const std::chrono::time_point<Clock, Duration>& timeout_time)
{
std::error_code ec;
bool b = wait_until(p, timeout_time, ec);
boost::process::detail::throw_error(ec, "wait_until error");
return b;
}
else if (wait_code == ::boost::detail::winapi::wait_timeout)
return false; //
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)
{
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(rel_time);
auto timeout = wait_impl(p, ec, ms.count());
return !ec && !timeout;
}
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;
}
}}}}

View File

@@ -353,10 +353,10 @@ struct initializer_builder<env_tag<wchar_t>>
The `env` property provides a functional way to modify the environment used by
the child process. If none is passed the environment is inherited from the father
process. Appending means that the environment will be interpreted as a ';' or ':'
seperated list as used in `PATH`.
separated list as used in `PATH`.
On both `posix` and `windows` the environment variables can be lists of strings,
seperated by ';'. This is typically used for the `PATH` variable.
separated by ';'. This is typically used for the `PATH` variable.
By default the environment will be inherited from the launching process,
which is also true if environment are modified with this initializer.

View File

@@ -94,8 +94,8 @@ struct entry : const_entry<Char, Environment>
explicit entry(string_type&& name, pointer data, environment_t & env) :
father(std::move(name), data, env) {}
explicit entry(string_type &&name, environment_t & env) :
father(std::move(name), env) {}
explicit entry(string_type &&name, environment_t & env_) :
father(std::move(name), env_) {}
entry(const entry&) = default;
entry& operator=(const entry&) = default;
@@ -472,17 +472,17 @@ public:
///Assign a string to the value
void assign(const string_type &value);
///Assign a set of strings to the entry; they will be seperated by ';' or ':'.
///Assign a set of strings to the entry; they will be separated by ';' or ':'.
void assign(const std::vector<string_type> &value);
///Append a string to the end of the entry, it will seperated by ';' or ':'.
///Append a string to the end of the entry, it will separated by ';' or ':'.
void append(const string_type &value);
///Reset the value
void clear();
///Assign a string to the entry.
entry &operator=(const string_type & value);
///Assign a set of strings to the entry; they will be seperated by ';' or ':'.
///Assign a set of strings to the entry; they will be separated by ';' or ':'.
entry &operator=(const std::vector<string_type> & value);
///Append a string to the end of the entry, it will seperated by ';' or ':'.
///Append a string to the end of the entry, it will separated by ';' or ':'.
entry &operator+=(const string_type & value);
};
@@ -592,17 +592,17 @@ public:
///Assign a string to the value
void assign(const string_type &value);
///Assign a set of strings to the entry; they will be seperated by ';' or ':'.
///Assign a set of strings to the entry; they will be separated by ';' or ':'.
void assign(const std::vector<string_type> &value);
///Append a string to the end of the entry, it will seperated by ';' or ':'.
///Append a string to the end of the entry, it will separated by ';' or ':'.
void append(const string_type &value);
///Reset the value
void clear();
///Assign a string to the entry.
entry &operator=(const string_type & value);
///Assign a set of strings to the entry; they will be seperated by ';' or ':'.
///Assign a set of strings to the entry; they will be separated by ';' or ':'.
entry &operator=(const std::vector<string_type> & value);
///Append a string to the end of the entry, it will seperated by ';' or ':'.
///Append a string to the end of the entry, it will separated by ';' or ':'.
entry &operator+=(const string_type & value);
};
@@ -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.

View File

@@ -26,10 +26,28 @@ namespace boost {
</programlisting>
\endxmlonly
*/
namespace boost { namespace process { namespace detail {
namespace boost {
namespace filesystem { class path; }
namespace process {
namespace detail {
struct exe_
{
template<typename = void>
inline exe_setter_<typename boost::filesystem::path::value_type> operator()(const boost::filesystem::path & pth) const
{
return exe_setter_<typename boost::filesystem::path::value_type>(pth.native());
}
template<typename = void>
inline exe_setter_<typename boost::filesystem::path::value_type> operator=(const boost::filesystem::path & pth) const
{
return exe_setter_<typename boost::filesystem::path::value_type>(pth.native());
}
template<typename Char>
inline exe_setter_<Char> operator()(const Char *s) const
{

View File

@@ -33,7 +33,7 @@ namespace boost {
namespace process {
namespace detail {
template<typename Tuple>
inline asio::io_service& get_io_service(const Tuple & tup);
inline asio::io_context& get_io_context(const Tuple & tup);
}
@@ -57,9 +57,9 @@ struct windows_executor;
#endif
using ::boost::process::detail::handler;
using ::boost::process::detail::api::require_io_service;
using ::boost::process::detail::api::require_io_context;
using ::boost::process::detail::api::async_handler;
using ::boost::process::detail::get_io_service;
using ::boost::process::detail::get_io_context;
using ::boost::process::detail::get_last_error;
using ::boost::process::detail::throw_last_error;
@@ -91,13 +91,13 @@ inline void throw_last_error(const std::string & msg);
inline void throw_last_error();
/** This function gets the io_service from the initializer sequence.
/** This function gets the io_context from the initializer sequence.
*
* \attention Yields a compile-time error if no `io_service` is provided.
* \attention Yields a compile-time error if no `io_context` is provided.
* \param seq The Sequence of the initializer.
*/
template<typename Sequence>
inline asio::io_service& get_io_service(const Sequence & seq);
inline asio::io_context& get_io_context(const Sequence & seq);
/** This class is the base for every initializer, to be used for extensions.
*
@@ -149,14 +149,14 @@ struct handler
};
/** Inheriting the class will tell the launching process that an `io_service` is
* needed. This should always be used when \ref get_io_service is used.
/** Inheriting the class will tell the launching process that an `io_context` is
* needed. This should always be used when \ref get_io_context is used.
*
*/
struct require_io_service {};
struct require_io_context {};
/** Inheriting this class will tell the launching function, that an event handler
* shall be invoked when the process exits. This automatically does also inherit
* \ref require_io_service.
* \ref require_io_context.
*
* You must add the following function to your implementation:
*
@@ -164,10 +164,10 @@ struct require_io_service {};
template<typename Executor>
std::function<void(int, const std::error_code&)> on_exit_handler(Executor & exec)
{
auto handler = this->handler;
return [handler](int exit_code, const std::error_code & ec)
auto handler_ = this->handler;
return [handler_](int exit_code, const std::error_code & ec)
{
handler(static_cast<int>(exit_code), ec);
handler_(static_cast<int>(exit_code), ec);
};
}
@@ -179,7 +179,7 @@ std::function<void(int, const std::error_code&)> on_exit_handler(Executor & exec
*
* \warning Cannot be used with \ref boost::process::spawn
*/
struct async_handler : handler, require_io_service
struct async_handler : handler, require_io_context
{
};
@@ -241,7 +241,7 @@ struct posix_executor
char **env = ::environ;
///The pid of the process - it will be -1 before invoking [fork](http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html), and after forking either 0 for the new process or a positive value if in the current process. */
pid_t pid = -1;
///This shared-pointer holds the exit code. It's done this way, so it can be shared between an `asio::io_service` and \ref child.
///This shared-pointer holds the exit code. It's done this way, so it can be shared between an `asio::io_context` and \ref child.
std::shared_ptr<std::atomic<int>> exit_status = std::make_shared<std::atomic<int>>(still_active);
///This function returns a const reference to the error state of the executor.
@@ -302,7 +302,7 @@ struct windows_executor
::boost::detail::winapi::PROCESS_INFORMATION_ proc_info{nullptr, nullptr, 0,0};
///This shared-pointer holds the exit code. It's done this way, so it can be shared between an `asio::io_service` and \ref child.
///This shared-pointer holds the exit code. It's done this way, so it can be shared between an `asio::io_context` and \ref child.
std::shared_ptr<std::atomic<int>> exit_status = std::make_shared<std::atomic<int>>(still_active);
///This function returns a const reference to the error state of the executor.

View File

@@ -91,14 +91,14 @@ child c2("c++filt", std_in<p);
Utilizing `boost.asio` asynchronous I/O is provided.
\code
boost::asio::io_service ios;
boost::asio::io_context ios;
std::future<std::string> output;
system("ls", std_out > output, ios);
auto res = fut.get();
\endcode
\note `boost/process/asnyc.hpp` must also be included for this to work.
\note `boost/process/async.hpp` must also be included for this to work.
\par Closing
@@ -371,7 +371,7 @@ std_err = buffer;
so you can wait for the input to be completed. It looks like this:
\code{.cpp}
std::future<void> fut;
boost::asio::io_service ios;
boost::asio::io_context ios;
std::string data;
child c("prog", std_in < buffer(data) > fut, ios);
fut.get();
@@ -380,7 +380,7 @@ fut.get();
\note `boost::asio::buffer` is also available in the `boost::process` namespace.
\warning This feature requires `boost/process/async.hpp` to be included and a reference to `boost::asio::io_service` to be passed to the launching function.
\warning This feature requires `boost/process/async.hpp` to be included and a reference to `boost::asio::io_context` to be passed to the launching function.
\subsection stdin_close Close
@@ -510,7 +510,7 @@ std_err = buffer;
\note `boost::asio::buffer` is also available in the `boost::process` namespace.
\warning This feature requires `boost/process/async.hpp` to be included and a reference to `boost::asio::io_service` to be passed to the launching function.
\warning This feature requires `boost/process/async.hpp` to be included and a reference to `boost::asio::io_context` to be passed to the launching function.
\subsection stdout_close Close

View File

@@ -223,7 +223,7 @@ private:
return false;
auto base = this->pbase();
auto wrt = _pipe.write(base,
std::ptrdiff_t wrt = _pipe.write(base,
static_cast<typename pipe_type::int_type>(this->pptr() - base));
std::ptrdiff_t diff = this->pptr() - base;
@@ -250,7 +250,7 @@ template<
>
class basic_ipstream : public std::basic_istream<CharT, Traits>
{
basic_pipebuf<CharT, Traits> _buf;
mutable basic_pipebuf<CharT, Traits> _buf;
public:
typedef basic_pipe<CharT, Traits> pipe_type;
@@ -262,7 +262,7 @@ public:
typedef typename Traits::off_type off_type ;
///Get access to the underlying stream_buf
basic_pipebuf<CharT, Traits>* rdbuf() const {return _buf;};
basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
///Default constructor.
basic_ipstream() : std::basic_istream<CharT, Traits>(nullptr)
@@ -272,7 +272,10 @@ public:
///Copy constructor.
basic_ipstream(const basic_ipstream & ) = delete;
///Move constructor.
basic_ipstream(basic_ipstream && ) = default;
basic_ipstream(basic_ipstream && lhs) : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf))
{
std::basic_istream<CharT, Traits>::rdbuf(&_buf);
}
///Move construct from a pipe.
basic_ipstream(pipe_type && p) : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(p))
@@ -289,7 +292,12 @@ public:
///Copy assignment.
basic_ipstream& operator=(const basic_ipstream & ) = delete;
///Move assignment
basic_ipstream& operator=(basic_ipstream && ) = default;
basic_ipstream& operator=(basic_ipstream && lhs)
{
std::basic_istream<CharT, Traits>::operator=(std::move(lhs));
_buf = std::move(lhs);
std::basic_istream<CharT, Traits>::rdbuf(&_buf);
};
///Move assignment of a pipe.
basic_ipstream& operator=(pipe_type && p)
{
@@ -326,7 +334,7 @@ template<
>
class basic_opstream : public std::basic_ostream<CharT, Traits>
{
basic_pipebuf<CharT, Traits> _buf;
mutable basic_pipebuf<CharT, Traits> _buf;
public:
typedef basic_pipe<CharT, Traits> pipe_type;
@@ -338,7 +346,7 @@ public:
///Get access to the underlying stream_buf
basic_pipebuf<CharT, Traits>* rdbuf() const {return _buf;};
basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
///Default constructor.
basic_opstream() : std::basic_ostream<CharT, Traits>(nullptr)
@@ -348,8 +356,10 @@ public:
///Copy constructor.
basic_opstream(const basic_opstream & ) = delete;
///Move constructor.
basic_opstream(basic_opstream && ) = default;
basic_opstream(basic_opstream && lhs) : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf))
{
std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
}
///Move construct from a pipe.
basic_opstream(pipe_type && p) : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(p))
{
@@ -363,7 +373,13 @@ public:
///Copy assignment.
basic_opstream& operator=(const basic_opstream & ) = delete;
///Move assignment
basic_opstream& operator=(basic_opstream && ) = default;
basic_opstream& operator=(basic_opstream && lhs)
{
std::basic_ostream<CharT, Traits>::operator=(std::move(lhs));
_buf = std::move(lhs);
std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
};
///Move assignment of a pipe.
basic_opstream& operator=(pipe_type && p)
{
@@ -401,7 +417,7 @@ template<
>
class basic_pstream : public std::basic_iostream<CharT, Traits>
{
basic_pipebuf<CharT, Traits> _buf;
mutable basic_pipebuf<CharT, Traits> _buf;
public:
typedef basic_pipe<CharT, Traits> pipe_type;
@@ -413,7 +429,7 @@ public:
///Get access to the underlying stream_buf
basic_pipebuf<CharT, Traits>* rdbuf() const {return _buf;};
basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
///Default constructor.
basic_pstream() : std::basic_iostream<CharT, Traits>(nullptr)
@@ -423,8 +439,10 @@ public:
///Copy constructor.
basic_pstream(const basic_pstream & ) = delete;
///Move constructor.
basic_pstream(basic_pstream && ) = default;
basic_pstream(basic_pstream && lhs) : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf))
{
std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
}
///Move construct from a pipe.
basic_pstream(pipe_type && p) : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(p))
{
@@ -438,7 +456,12 @@ public:
///Copy assignment.
basic_pstream& operator=(const basic_pstream & ) = delete;
///Move assignment
basic_pstream& operator=(basic_pstream && ) = default;
basic_pstream& operator=(basic_pstream && lhs)
{
std::basic_istream<CharT, Traits>::operator=(std::move(lhs));
_buf = std::move(lhs);
std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
};
///Move assignment of a pipe.
basic_pstream& operator=(pipe_type && p)
{

View File

@@ -39,7 +39,7 @@ namespace boost { namespace process {
*
* \param filename The base of the filename to find
*
* \param path the set of paths so search, defaults to "PATH" environment variable.
* \param path the set of paths to search, defaults to the "PATH" environment variable.
*
* \returns the absolute path to the executable filename or an
* empty string if filename isn't found

View File

@@ -42,7 +42,7 @@ but will also cause the system to be unable to wait for the child to exit.
\note This will set `SIGCHLD` to `SIGIGN` on posix.
\warning This function does not allow asynchronous operations, since it cannot wait for the end of the process.
It will fail to compile if a reference to `boost::asio::io_service` is passed.
It will fail to compile if a reference to `boost::asio::io_context` is passed.
*/
template<typename ...Args>

View File

@@ -13,6 +13,7 @@
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/handler.hpp>
#include <boost/process/locale.hpp>
#include <boost/process/detail/traits/wchar_t.hpp>
#if defined (BOOST_POSIX_API)
#include <boost/process/detail/posix/start_dir.hpp>

View File

@@ -22,6 +22,7 @@
#include <boost/process/child.hpp>
#include <boost/process/detail/async_handler.hpp>
#include <boost/process/detail/execute_impl.hpp>
#include <boost/asio/post.hpp>
#include <type_traits>
#include <mutex>
#include <condition_variable>
@@ -48,10 +49,10 @@ struct system_impl_success_check : handler
template<typename IoService, typename ...Args>
inline int system_impl(
std::true_type, /*needs ios*/
std::true_type, /*has io_service*/
std::true_type, /*has io_context*/
Args && ...args)
{
IoService & ios = ::boost::process::detail::get_io_service_var(args...);
IoService & ios = ::boost::process::detail::get_io_context_var(args...);
system_impl_success_check check;
@@ -62,7 +63,7 @@ inline int system_impl(
::boost::process::on_exit(
[&](int, const std::error_code&)
{
ios.post([&]{exited.store(true);});
boost::asio::post(ios.get_executor(), [&]{exited.store(true);});
}));
if (!c.valid() || !check.succeeded)
return -1;
@@ -76,7 +77,7 @@ inline int system_impl(
template<typename IoService, typename ...Args>
inline int system_impl(
std::true_type, /*needs ios */
std::false_type, /*has io_service*/
std::false_type, /*has io_context*/
Args && ...args)
{
IoService ios;
@@ -85,6 +86,8 @@ inline int system_impl(
return -1;
ios.run();
if (c.running())
c.wait();
return c.exit_code();
}
@@ -92,7 +95,7 @@ inline int system_impl(
template<typename IoService, typename ...Args>
inline int system_impl(
std::false_type, /*needs ios*/
std::true_type, /*has io_service*/
std::true_type, /*has io_context*/
Args && ...args)
{
child c(std::forward<Args>(args)...);
@@ -105,7 +108,7 @@ inline int system_impl(
template<typename IoService, typename ...Args>
inline int system_impl(
std::false_type, /*has async */
std::false_type, /*has io_service*/
std::false_type, /*has io_context*/
Args && ...args)
{
child c(std::forward<Args>(args)...
@@ -131,19 +134,19 @@ int ret = system("ls");
\attention Using this function with synchronous pipes leads to many potential deadlocks.
When using this function with an asynchronous properties and NOT passing an io_service object,
the system function will create one and run it. When the io_service is passed to the function,
the system function will check if it is active, and call the io_service::run function if not.
When using this function with an asynchronous properties and NOT passing an io_context object,
the system function will create one and run it. When the io_context is passed to the function,
the system function will check if it is active, and call the io_context::run function if not.
*/
template<typename ...Args>
inline int system(Args && ...args)
{
typedef typename ::boost::process::detail::needs_io_service<Args...>::type
typedef typename ::boost::process::detail::needs_io_context<Args...>::type
need_ios;
typedef typename ::boost::process::detail::has_io_service<Args...>::type
typedef typename ::boost::process::detail::has_io_context<Args...>::type
has_ios;
return ::boost::process::detail::system_impl<boost::asio::io_service>(
return ::boost::process::detail::system_impl<boost::asio::io_context>(
need_ios(), has_ios(),
std::forward<Args>(args)...);
}

View File

@@ -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,24 +35,26 @@ 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.
constexpr ::boost::process::detail::windows::show_window<::boost::detail::winapi::SW_HIDE_ > hide;
constexpr ::boost::process::detail::windows::show_window<::boost::winapi::SW_HIDE_ > hide;
///Activates the window and displays it as a maximized window.
constexpr ::boost::process::detail::windows::show_window<::boost::detail::winapi::SW_SHOWMAXIMIZED_ > maximized;
constexpr ::boost::process::detail::windows::show_window<::boost::winapi::SW_SHOWMAXIMIZED_ > maximized;
///Activates the window and displays it as a minimized window.
constexpr ::boost::process::detail::windows::show_window<::boost::detail::winapi::SW_SHOWMINIMIZED_ > minimized;
constexpr ::boost::process::detail::windows::show_window<::boost::winapi::SW_SHOWMINIMIZED_ > minimized;
///Displays the window as a minimized window. This value is similar to `minimized`, except the window is not activated.
constexpr ::boost::process::detail::windows::show_window<::boost::detail::winapi::SW_SHOWMINNOACTIVE_> minimized_not_active;
constexpr ::boost::process::detail::windows::show_window<::boost::winapi::SW_SHOWMINNOACTIVE_> minimized_not_active;
///Displays a window in its most recent size and position. This value is similar to show_normal`, except that the window is not activated.
constexpr ::boost::process::detail::windows::show_window<::boost::detail::winapi::SW_SHOWNOACTIVATE_ > not_active;
constexpr ::boost::process::detail::windows::show_window<::boost::winapi::SW_SHOWNOACTIVATE_ > not_active;
///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::detail::winapi::SW_SHOWNORMAL_ > show;
constexpr ::boost::process::detail::windows::show_window<::boost::winapi::SW_SHOWNORMAL_ > show;
///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::detail::winapi::SW_SHOWNORMAL_ > show_normal;
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;
}}}