updated boost on windows

This commit is contained in:
Bassem Girgis
2019-08-13 21:48:48 -05:00
parent 7d77d485fd
commit b40a3bee82
5162 changed files with 473027 additions and 116452 deletions

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;
}
}}}}