mirror of
https://github.com/boostorg/process.git
synced 2026-01-20 16:52:14 +00:00
Compare commits
54 Commits
boost-1.82
...
issue/285
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ad4fd3ccf | ||
|
|
502dc48753 | ||
|
|
402acc151a | ||
|
|
0503b0997c | ||
|
|
8d372cb510 | ||
|
|
bfb1ebb5bd | ||
|
|
c005adc8fc | ||
|
|
5cab462710 | ||
|
|
ccd46dc692 | ||
|
|
b3c8c3a8da | ||
|
|
4dd6f28094 | ||
|
|
d73f228469 | ||
|
|
ccd1717588 | ||
|
|
9a4aeab97e | ||
|
|
d66dce11bd | ||
|
|
fc38699a4b | ||
|
|
a859c5151c | ||
|
|
8c2f403841 | ||
|
|
6fb2702a79 | ||
|
|
6cd4244f05 | ||
|
|
0c42a58eac | ||
|
|
f269236d38 | ||
|
|
4b413d34f4 | ||
|
|
1403af769b | ||
|
|
964f6d3f7e | ||
|
|
bccf42a3ec | ||
|
|
70c7ae694f | ||
|
|
3211afda4a | ||
|
|
d3f006acd4 | ||
|
|
99633a6e42 | ||
|
|
1e614ee43e | ||
|
|
0e3358705d | ||
|
|
27a35f452d | ||
|
|
8fff7283ed | ||
|
|
611dac143f | ||
|
|
8d93576b94 | ||
|
|
f703845011 | ||
|
|
abd052e09f | ||
|
|
a3304564c6 | ||
|
|
5865c6b449 | ||
|
|
4c872c0a0d | ||
|
|
feabbee098 | ||
|
|
a5b6e70c39 | ||
|
|
347fc68476 | ||
|
|
61ff12c8da | ||
|
|
bd8e81153c | ||
|
|
5fde6bec9f | ||
|
|
cf64f7dc6a | ||
|
|
8355c3e1b6 | ||
|
|
de797e388d | ||
|
|
fc33435f8b | ||
|
|
f45ec624db | ||
|
|
9682056278 | ||
|
|
a00115b454 |
49
.github/workflows/ci.yml
vendored
49
.github/workflows/ci.yml
vendored
@@ -199,52 +199,3 @@ jobs:
|
||||
run: |
|
||||
cd ../boost-root
|
||||
b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker
|
||||
|
||||
posix-cmake-subdir:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
- os: ubuntu-20.04
|
||||
- os: ubuntu-22.04
|
||||
- os: macos-11
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
|
||||
LIBRARY=${GITHUB_REPOSITORY#*/}
|
||||
echo LIBRARY: $LIBRARY
|
||||
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
|
||||
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
|
||||
echo GITHUB_REF: $GITHUB_REF
|
||||
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
|
||||
REF=${REF#refs/heads/}
|
||||
echo REF: $REF
|
||||
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
|
||||
echo BOOST_BRANCH: $BOOST_BRANCH
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
|
||||
|
||||
- name: Use library with add_subdirectory
|
||||
run: |
|
||||
cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test
|
||||
mkdir __build__ && cd __build__
|
||||
cmake ..
|
||||
cmake --build .
|
||||
ctest --output-on-failure --no-tests=error
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ In this library the following functions are used for the creation of unnamed pip
|
||||
As the name suggests, named pipes have a string identifier. This means that a
|
||||
handle to them can be obtained with the identifier, too.
|
||||
|
||||
The implementation on posix uses [@(http://pubs.opengroup.org/onlinepubs/009695399/functions/mkfifo.html fifos],
|
||||
The implementation on posix uses [@http://pubs.opengroup.org/onlinepubs/009695399/functions/mkfifo.html fifos],
|
||||
which means, that the named pipe behaves like a file.
|
||||
|
||||
Windows does provide a facility called [@https://msdn.microsoft.com/en-us/library/windows/desktop/aa365150(v=vs.85).aspx named pipes],
|
||||
|
||||
@@ -57,7 +57,7 @@ file-handles for the subprocess.
|
||||
|
||||
Certain parts of boost.process were not as reliable as they should've been.
|
||||
|
||||
This concerns especially the `wait_for`` and `wait_until` functions on the process.
|
||||
This concerns especially the `wait_for` and `wait_until` functions on the process.
|
||||
The latter are easy to do on windows, but posix does not provide an API for this.
|
||||
Thus the wait_for used signals or fork, which was all but safe.
|
||||
Since process v2 is based on asio and thus supports cancellation,
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
#include <system_error>
|
||||
#include <boost/system/api_config.hpp>
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/process/exception.hpp>
|
||||
#include <boost/assert/source_location.hpp>
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
#include <errno.h>
|
||||
@@ -71,31 +73,33 @@ inline std::error_code get_last_error() noexcept
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void throw_last_error(const std::string & msg)
|
||||
inline void throw_last_error(const std::string & msg, boost::source_location const & loc = boost::source_location())
|
||||
{
|
||||
throw process_error(get_last_error(), msg);
|
||||
boost::throw_exception(process_error(get_last_error(), msg), loc);
|
||||
}
|
||||
|
||||
inline void throw_last_error(const char * msg)
|
||||
inline void throw_last_error(const char * msg, boost::source_location const & loc = boost::source_location())
|
||||
{
|
||||
throw process_error(get_last_error(), msg);
|
||||
boost::throw_exception(process_error(get_last_error(), msg), loc);
|
||||
}
|
||||
|
||||
inline void throw_last_error()
|
||||
inline void throw_last_error(boost::source_location const & loc = boost::source_location())
|
||||
{
|
||||
throw process_error(get_last_error());
|
||||
boost::throw_exception(process_error(get_last_error()), loc);
|
||||
}
|
||||
|
||||
inline void throw_error(const std::error_code& ec)
|
||||
inline void throw_error(const std::error_code& ec,
|
||||
boost::source_location const & loc = boost::source_location())
|
||||
{
|
||||
if (ec)
|
||||
throw process_error(ec);
|
||||
boost::throw_exception(process_error(ec), loc);
|
||||
}
|
||||
|
||||
inline void throw_error(const std::error_code& ec, const char* msg)
|
||||
inline void throw_error(const std::error_code& ec, const char* msg,
|
||||
boost::source_location const & loc = boost::source_location())
|
||||
{
|
||||
if (ec)
|
||||
throw process_error(ec, msg);
|
||||
boost::throw_exception(process_error(ec, msg), loc);
|
||||
}
|
||||
|
||||
template<typename Char> constexpr Char null_char();
|
||||
|
||||
@@ -71,7 +71,7 @@ struct async_out_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;
|
||||
boost::asio::async_read(*pipe, buf,
|
||||
|
||||
@@ -112,7 +112,10 @@ struct exe_cmd_init<char> : boost::process::detail::api::handler_base_ext
|
||||
{
|
||||
if (exe.empty()) //cmd style
|
||||
{
|
||||
exec.exe = args.front().c_str();
|
||||
if (args.empty())
|
||||
exec.exe = "";
|
||||
else
|
||||
exec.exe = args.front().c_str();
|
||||
exec.cmd_style = true;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -77,12 +77,9 @@ public:
|
||||
void assign_source(native_handle_type h) { _source = h;}
|
||||
void assign_sink (native_handle_type h) { _sink = h;}
|
||||
|
||||
|
||||
|
||||
|
||||
int_type write(const char_type * data, int_type count)
|
||||
{
|
||||
int_type write_len;
|
||||
ssize_t write_len;
|
||||
while ((write_len = ::write(_sink, data, count * sizeof(char_type))) == -1)
|
||||
{
|
||||
//Try again if interrupted
|
||||
@@ -90,19 +87,19 @@ public:
|
||||
if (err != EINTR)
|
||||
::boost::process::detail::throw_last_error();
|
||||
}
|
||||
return write_len;
|
||||
return static_cast<int_type>(write_len);
|
||||
}
|
||||
int_type read(char_type * data, int_type count)
|
||||
{
|
||||
int_type read_len;
|
||||
while ((read_len = static_cast<int_type>(::read(_source, data, count * sizeof(char_type)))) == -1)
|
||||
ssize_t read_len;
|
||||
while ((read_len = ::read(_source, data, count * sizeof(char_type))) == -1)
|
||||
{
|
||||
//Try again if interrupted
|
||||
auto err = errno;
|
||||
if (err != EINTR)
|
||||
::boost::process::detail::throw_last_error();
|
||||
}
|
||||
return read_len;
|
||||
return static_cast<int_type>(read_len);
|
||||
}
|
||||
|
||||
bool is_open() const
|
||||
|
||||
@@ -445,7 +445,7 @@ child executor<Sequence>::invoke(boost::mpl::false_, boost::mpl::false_)
|
||||
if (_ec)
|
||||
{
|
||||
//if an error occurred we need to reap the child process
|
||||
::waitpid(this->pid, nullptr, WNOHANG);
|
||||
::waitpid(this->pid, nullptr, 0);
|
||||
boost::fusion::for_each(seq, call_on_error(*this, _ec));
|
||||
return child();
|
||||
}
|
||||
|
||||
@@ -61,6 +61,10 @@ inline std::string build_args(const std::string & exe, std::vector<std::string>
|
||||
arg += '"';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
arg = "\"\"";
|
||||
}
|
||||
|
||||
if (!st.empty())//first one does not need a preceding space
|
||||
st += ' ';
|
||||
@@ -105,6 +109,10 @@ inline std::wstring build_args(const std::wstring & exe, std::vector<std::wstrin
|
||||
arg += '"';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
arg = L"\"\"";
|
||||
}
|
||||
|
||||
if (!st.empty())//first one does not need a preceding space
|
||||
st += L' ';
|
||||
|
||||
@@ -158,7 +158,7 @@ basic_pipe<Char, Traits>::basic_pipe(const std::string & name)
|
||||
::boost::process::detail::throw_last_error("create_named_pipe() failed");
|
||||
|
||||
::boost::winapi::HANDLE_ sink = boost::winapi::create_file(
|
||||
name.c_str(),
|
||||
name_.c_str(),
|
||||
::boost::winapi::GENERIC_WRITE_, 0, nullptr,
|
||||
OPEN_EXISTING_,
|
||||
FILE_FLAG_OVERLAPPED_, //to allow read
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <boost/winapi/handles.hpp>
|
||||
#include <boost/process/detail/used_handles.hpp>
|
||||
#include <boost/process/detail/handler_base.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace process { namespace detail { namespace windows {
|
||||
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
#include <boost/winapi/handles.hpp>
|
||||
#include <boost/process/detail/used_handles.hpp>
|
||||
#include <boost/process/detail/handler_base.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace process { namespace detail { namespace windows {
|
||||
|
||||
|
||||
|
||||
template<int p1, int p2>
|
||||
struct pipe_out : public ::boost::process::detail::handler_base, ::boost::process::detail::uses_handles
|
||||
{
|
||||
|
||||
@@ -263,7 +263,7 @@ public:
|
||||
auto st1 = key + ::boost::process::detail::equal_sign<Char>();
|
||||
while (*p != nullptr)
|
||||
{
|
||||
const int len = std::char_traits<Char>::length(*p);
|
||||
const std::size_t len = std::char_traits<Char>::length(*p);
|
||||
if ((std::distance(st1.begin(), st1.end()) < len)
|
||||
&& std::equal(st1.begin(), st1.end(), *p))
|
||||
break;
|
||||
@@ -277,7 +277,7 @@ public:
|
||||
auto st1 = key + ::boost::process::detail::equal_sign<Char>();
|
||||
while (*p != nullptr)
|
||||
{
|
||||
const int len = std::char_traits<Char>::length(*p);
|
||||
const std::size_t len = std::char_traits<Char>::length(*p);
|
||||
if ((std::distance(st1.begin(), st1.end()) < len)
|
||||
&& std::equal(st1.begin(), st1.end(), *p))
|
||||
break;
|
||||
@@ -292,8 +292,9 @@ public:
|
||||
auto st1 = st + ::boost::process::detail::equal_sign<Char>();
|
||||
while (*p != nullptr)
|
||||
{
|
||||
const int len = std::char_traits<Char>::length(*p);
|
||||
if ((std::distance(st1.begin(), st1.end()) < len)
|
||||
const std::size_t len = std::char_traits<Char>::length(*p);
|
||||
if ((std::distance(st1.begin(), st1.end()) <
|
||||
static_cast<typename string_type::iterator::difference_type>(len))
|
||||
&& std::equal(st1.begin(), st1.end(), *p))
|
||||
return 1u;
|
||||
p++;
|
||||
|
||||
@@ -122,10 +122,14 @@ struct basic_pipebuf : std::basic_streambuf<CharT, Traits>
|
||||
|
||||
///Destructor -> writes the frest of the data
|
||||
~basic_pipebuf()
|
||||
try
|
||||
{
|
||||
if (basic_pipebuf::is_open())
|
||||
basic_pipebuf::overflow(Traits::eof());
|
||||
}
|
||||
catch (process_error & )
|
||||
{
|
||||
}
|
||||
|
||||
///Move construct from a pipe.
|
||||
basic_pipebuf(pipe_type && p) : _pipe(std::move(p)),
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/cstring_ref.hpp>
|
||||
#include <boost/process/v2/detail/utf8.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <numeric>
|
||||
@@ -501,8 +502,8 @@ struct key
|
||||
|
||||
template< class Source >
|
||||
key( const Source& source,
|
||||
decltype(source.data()) = nullptr,
|
||||
decltype(source.size()) = 0u)
|
||||
decltype(std::declval<Source>().data()) = nullptr,
|
||||
decltype(std::declval<Source>().size()) = 0u)
|
||||
: value_(
|
||||
BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
|
||||
source.data(), source.size()))
|
||||
@@ -724,8 +725,8 @@ struct value
|
||||
|
||||
template< class Source >
|
||||
value( const Source& source,
|
||||
decltype(source.data()) = nullptr,
|
||||
decltype(source.size()) = 0u)
|
||||
decltype(std::declval<Source>().data()) = nullptr,
|
||||
decltype(std::declval<Source>().size()) = 0u)
|
||||
: value_(BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
|
||||
source.data(), source.size()))
|
||||
{
|
||||
@@ -974,8 +975,8 @@ struct key_value_pair
|
||||
|
||||
template< class Source >
|
||||
key_value_pair( const Source& source,
|
||||
decltype(source.data()) = nullptr,
|
||||
decltype(source.size()) = 0u)
|
||||
decltype(std::declval<Source>().data()) = nullptr,
|
||||
decltype(std::declval<Source>().size()) = 0u)
|
||||
: value_(BOOST_PROCESS_V2_NAMESPACE::detail::conv_string<char_type, traits_type>(
|
||||
source.data(), source.size()))
|
||||
{
|
||||
@@ -1743,8 +1744,8 @@ struct process_environment
|
||||
return build_env(env_buffer);
|
||||
}
|
||||
|
||||
process_environment(std::initializer_list<string_view> sv) : unicode_env{build_env(sv, "")} {}
|
||||
process_environment(std::initializer_list<wstring_view> sv) : unicode_env{build_env(sv, L"")} {}
|
||||
process_environment(std::initializer_list<string_view> sv) : unicode_env{build_env(sv)} {}
|
||||
process_environment(std::initializer_list<wstring_view> sv) : unicode_env{build_env(sv)} {}
|
||||
|
||||
template<typename Args>
|
||||
process_environment(Args && args) : unicode_env{build_env(std::forward<Args>(args))}
|
||||
@@ -1804,6 +1805,7 @@ struct process_environment
|
||||
}
|
||||
|
||||
|
||||
BOOST_PROCESS_V2_DECL
|
||||
error_code on_setup(posix::default_launcher & launcher,
|
||||
const filesystem::path &, const char * const *);
|
||||
|
||||
@@ -1885,6 +1887,8 @@ struct hash<BOOST_PROCESS_V2_NAMESPACE::environment::key_value_pair>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_HEADER_ONLY)
|
||||
|
||||
|
||||
#include <boost/process/v2/impl/environment.ipp>
|
||||
#include <boost/process/v2/detail/impl/environment.ipp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -94,12 +94,19 @@ inline int evaluate_exit_code(int code)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/** Convert the exit-code in a completion into an error if the actual error isn't set.
|
||||
/// @{
|
||||
/** Helper to subsume an exit-code into an error_code if there's no actual error isn't set.
|
||||
* @code {.cpp}
|
||||
* process proc{ctx, "exit", {"1"}};
|
||||
*
|
||||
* proc.async_wait(code_as_error(
|
||||
* proc.async_wait(
|
||||
* asio::deferred(
|
||||
* [&proc](error_code ec, int)
|
||||
* {
|
||||
* return asio::deferred.values(
|
||||
* check_exit_code(ec, proc.native_exit_code())
|
||||
* );
|
||||
*
|
||||
* [](error_code ec)
|
||||
* {
|
||||
* assert(ec.value() == 10);
|
||||
@@ -107,144 +114,19 @@ inline int evaluate_exit_code(int code)
|
||||
* }));
|
||||
*
|
||||
* @endcode
|
||||
*/
|
||||
template<typename CompletionToken>
|
||||
struct code_as_error_t
|
||||
*/
|
||||
|
||||
inline error_code check_exit_code(
|
||||
error_code &ec, native_exit_code_type native_code,
|
||||
const error_category & category = error::get_exit_code_category())
|
||||
{
|
||||
CompletionToken token_;
|
||||
const error_category & category;
|
||||
|
||||
template<typename Token_>
|
||||
code_as_error_t(Token_ && token, const error_category & category)
|
||||
: token_(std::forward<Token_>(token)), category(category)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/// Deduction function for code_as_error_t.
|
||||
template<typename CompletionToken>
|
||||
code_as_error_t<CompletionToken> code_as_error(
|
||||
CompletionToken && token,
|
||||
const error_category & category = error::get_exit_code_category())
|
||||
{
|
||||
return code_as_error_t<typename std::decay<CompletionToken>::type>(
|
||||
std::forward<CompletionToken>(token), category);
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename Handler>
|
||||
struct code_as_error_handler
|
||||
{
|
||||
typedef void result_type;
|
||||
|
||||
template<typename H>
|
||||
code_as_error_handler(H && h, const error_category & category)
|
||||
: handler_(std::forward<H>(h)), category(category)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(error_code ec, native_exit_code_type code)
|
||||
{
|
||||
if (!ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, code, category)
|
||||
std::move(handler_)(ec);
|
||||
}
|
||||
|
||||
|
||||
Handler handler_;
|
||||
const error_category & category;
|
||||
};
|
||||
|
||||
if (!ec)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, native_code, category);
|
||||
return ec;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
|
||||
#if !defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
namespace boost
|
||||
{
|
||||
#endif
|
||||
namespace asio
|
||||
{
|
||||
|
||||
template <typename CompletionToken>
|
||||
struct async_result<
|
||||
BOOST_PROCESS_V2_NAMESPACE::code_as_error_t<CompletionToken>,
|
||||
void(BOOST_PROCESS_V2_NAMESPACE::error_code,
|
||||
BOOST_PROCESS_V2_NAMESPACE::native_exit_code_type)>
|
||||
{
|
||||
using signature = void(BOOST_PROCESS_V2_NAMESPACE::error_code);
|
||||
using return_type = typename async_result<CompletionToken, void(BOOST_PROCESS_V2_NAMESPACE::error_code)>::return_type;
|
||||
|
||||
|
||||
template <typename Initiation>
|
||||
struct init_wrapper
|
||||
{
|
||||
init_wrapper(Initiation init)
|
||||
: initiation_(std::move(init))
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Handler, typename... Args>
|
||||
void operator()(
|
||||
Handler && handler,
|
||||
const BOOST_PROCESS_V2_NAMESPACE::error_category & cat,
|
||||
Args && ... args)
|
||||
{
|
||||
std::move(initiation_)(
|
||||
BOOST_PROCESS_V2_NAMESPACE::detail::code_as_error_handler<typename decay<Handler>::type>(
|
||||
std::forward<Handler>(handler), cat),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
Initiation initiation_;
|
||||
|
||||
};
|
||||
|
||||
template <typename Initiation, typename RawCompletionToken, typename... Args>
|
||||
static BOOST_PROCESS_V2_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, signature,
|
||||
(async_initiate<CompletionToken, signature>(
|
||||
declval<init_wrapper<typename decay<Initiation>::type> >(),
|
||||
declval<CompletionToken&>(),
|
||||
declval<BOOST_ASIO_MOVE_ARG(Args)>()...)))
|
||||
initiate(
|
||||
Initiation && initiation,
|
||||
RawCompletionToken && token,
|
||||
Args &&... args)
|
||||
{
|
||||
return async_initiate<CompletionToken, signature>(
|
||||
init_wrapper<typename decay<Initiation>::type>(
|
||||
std::forward<Initiation>(initiation)),
|
||||
token.token_,
|
||||
token.category,
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template<template <typename, typename> class Associator, typename Handler, typename DefaultCandidate>
|
||||
struct associator<Associator,
|
||||
BOOST_PROCESS_V2_NAMESPACE::detail::code_as_error_handler<Handler>, DefaultCandidate>
|
||||
: Associator<Handler, DefaultCandidate>
|
||||
{
|
||||
static typename Associator<Handler, DefaultCandidate>::type get(
|
||||
const BOOST_PROCESS_V2_NAMESPACE::detail::code_as_error_handler<Handler> & h,
|
||||
const DefaultCandidate& c = DefaultCandidate()) noexcept
|
||||
{
|
||||
return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#if !defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
} // boost
|
||||
#endif
|
||||
|
||||
|
||||
#endif //BOOST_PROCESS_V2_EXIT_CODE_HPP
|
||||
@@ -20,6 +20,11 @@ BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace ext {
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
BOOST_PROCESS_V2_DECL shell cmd(HANDLE handle, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL shell cmd(HANDLE handle);
|
||||
#endif
|
||||
|
||||
/// @{
|
||||
/// Get the argument vector of another process
|
||||
BOOST_PROCESS_V2_DECL shell cmd(pid_type pid, error_code & ec);
|
||||
|
||||
@@ -15,6 +15,11 @@ BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace ext {
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
BOOST_PROCESS_V2_DECL filesystem::path cwd(HANDLE handle, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL filesystem::path cwd(HANDLE handle);
|
||||
#endif
|
||||
|
||||
/// @{
|
||||
/// Obtain the current path of another process
|
||||
BOOST_PROCESS_V2_DECL filesystem::path cwd(pid_type pid, error_code & ec);
|
||||
@@ -42,12 +47,6 @@ BOOST_PROCESS_V2_DECL filesystem::path cwd(basic_process_handle<Executor> & hand
|
||||
|
||||
/// @}
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
BOOST_PROCESS_V2_DECL filesystem::path cwd(HANDLE handle, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL filesystem::path cwd(HANDLE handle);
|
||||
#endif
|
||||
|
||||
|
||||
} // namespace ext
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
@@ -109,6 +109,11 @@ struct env_view
|
||||
detail::ext::native_env_handle_deleter> handle_;
|
||||
};
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
BOOST_PROCESS_V2_DECL env_view env(HANDLE handle, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL env_view env(HANDLE handle);
|
||||
#endif
|
||||
|
||||
/// @{
|
||||
/// Get the environment of another process.
|
||||
BOOST_PROCESS_V2_DECL env_view env(pid_type pid, error_code & ec);
|
||||
@@ -136,10 +141,6 @@ BOOST_PROCESS_V2_DECL env_view env(basic_process_handle<Executor> & handle)
|
||||
|
||||
/// @}
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
BOOST_PROCESS_V2_DECL env_view env(HANDLE handle, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL env_view env(HANDLE handle);
|
||||
#endif
|
||||
|
||||
|
||||
} // namespace ext
|
||||
|
||||
@@ -16,6 +16,11 @@ BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
|
||||
namespace ext {
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
BOOST_PROCESS_V2_DECL filesystem::path exe(HANDLE handle, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL filesystem::path exe(HANDLE handle);
|
||||
#endif
|
||||
|
||||
/// @{
|
||||
/// Return the executable of another process by pid or handle.
|
||||
BOOST_PROCESS_V2_DECL filesystem::path exe(pid_type pid, error_code & ec);
|
||||
@@ -45,11 +50,6 @@ filesystem::path exe(basic_process_handle<Executor> & handle)
|
||||
|
||||
///@}
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
BOOST_PROCESS_V2_DECL filesystem::path exe(HANDLE handle, error_code & ec);
|
||||
BOOST_PROCESS_V2_DECL filesystem::path exe(HANDLE handle);
|
||||
#endif
|
||||
|
||||
} // namespace ext
|
||||
|
||||
BOOST_PROCESS_V2_END_NAMESPACE
|
||||
|
||||
@@ -55,7 +55,7 @@ struct exit_code_category final : public error_category
|
||||
}
|
||||
std::string message(int status) const
|
||||
{
|
||||
switch (status)
|
||||
switch (evaluate_exit_code(status))
|
||||
{
|
||||
case v2::detail::still_active:
|
||||
return "still-active";
|
||||
|
||||
@@ -109,42 +109,6 @@ struct basic_popen : basic_process<Executor>
|
||||
));
|
||||
}
|
||||
|
||||
/// Construct a child from a property list and launch it using the default process launcher.
|
||||
template<typename ... Inits>
|
||||
explicit basic_popen(
|
||||
executor_type executor,
|
||||
const filesystem::path& exe,
|
||||
std::initializer_list<wstring_view> args,
|
||||
Inits&&... inits)
|
||||
: basic_process<Executor>(executor)
|
||||
{
|
||||
this->basic_process<Executor>::operator=(
|
||||
default_process_launcher()(
|
||||
this->get_executor(), exe, args,
|
||||
std::forward<Inits>(inits)...,
|
||||
process_stdio{stdin_, stdout_}
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
/// Construct a child from a property list and launch it using the default process launcher.
|
||||
template<typename Launcher, typename ... Inits>
|
||||
explicit basic_popen(
|
||||
Launcher && launcher,
|
||||
executor_type executor,
|
||||
const filesystem::path& exe,
|
||||
std::initializer_list<wstring_view> args,
|
||||
Inits&&... inits)
|
||||
: basic_process<Executor>(executor)
|
||||
{
|
||||
this->basic_process<Executor>::operator=(
|
||||
std::forward<Launcher>(launcher)(
|
||||
this->get_executor(), exe, args,
|
||||
std::forward<Inits>(inits)...,
|
||||
process_stdio{stdin_, stdout_}
|
||||
));
|
||||
}
|
||||
|
||||
/// Construct a child from a property list and launch it using the default process launcher.
|
||||
template<typename Args, typename ... Inits>
|
||||
explicit basic_popen(
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/cstring_ref.hpp>
|
||||
#include <boost/process/v2/posix/detail/close_handles.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/detail/utf8.hpp>
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_STANDALONE)
|
||||
@@ -313,7 +314,7 @@ struct default_launcher
|
||||
auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
asio::detail::throw_error(ec, "default_launcher");
|
||||
v2::detail::throw_error(ec, "default_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
@@ -344,7 +345,7 @@ struct default_launcher
|
||||
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
asio::detail::throw_error(ec, "default_launcher");
|
||||
v2::detail::throw_error(ec, "default_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ struct fork_and_forget_launcher : default_launcher
|
||||
auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
asio::detail::throw_error(ec, "fork_and_forget_launcher");
|
||||
v2::detail::throw_error(ec, "fork_and_forget_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
@@ -60,7 +60,7 @@ struct fork_and_forget_launcher : default_launcher
|
||||
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
asio::detail::throw_error(ec, "fork_and_forget_launcher");
|
||||
v2::detail::throw_error(ec, "fork_and_forget_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ struct pdfork_launcher : default_launcher
|
||||
auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
asio::detail::throw_error(ec, "pdfork_launcher");
|
||||
v2::detail::throw_error(ec, "pdfork_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
@@ -65,7 +65,7 @@ struct pdfork_launcher : default_launcher
|
||||
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
asio::detail::throw_error(ec, "pdfork_launcher");
|
||||
v2::detail::throw_error(ec, "pdfork_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ struct vfork_launcher : default_launcher
|
||||
auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
asio::detail::throw_error(ec, "default_launcher");
|
||||
v2::detail::throw_error(ec, "default_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
@@ -62,7 +62,7 @@ struct vfork_launcher : default_launcher
|
||||
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
asio::detail::throw_error(ec, "default_launcher");
|
||||
v2::detail::throw_error(ec, "default_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
@@ -101,7 +101,6 @@ struct vfork_launcher : default_launcher
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_child);
|
||||
ec = detail::on_exec_setup(*this, executable, argv, inits...);
|
||||
if (!ec)
|
||||
close_all_fds(ec);
|
||||
@@ -110,7 +109,7 @@ struct vfork_launcher : default_launcher
|
||||
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category())
|
||||
detail::on_exec_error(*this, executable, argv, ec, inits...);
|
||||
::exit(EXIT_FAILURE);
|
||||
::_exit(EXIT_FAILURE);
|
||||
return basic_process<Executor>{exec};
|
||||
}
|
||||
ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_parent);
|
||||
|
||||
@@ -93,17 +93,7 @@ struct basic_process
|
||||
: basic_process(default_process_launcher()(std::move(executor), exe, args, std::forward<Inits>(inits)...))
|
||||
{
|
||||
}
|
||||
/// Construct a child from a property list and launch it using the default launcher..
|
||||
template<typename ... Inits>
|
||||
explicit basic_process(
|
||||
executor_type executor,
|
||||
const filesystem::path& exe,
|
||||
std::initializer_list<wstring_view> args,
|
||||
Inits&&... inits)
|
||||
: basic_process(default_process_launcher()(std::move(executor), exe, args, std::forward<Inits>(inits)...))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// Construct a child from a property list and launch it using the default launcher..
|
||||
template<typename Args, typename ... Inits>
|
||||
explicit basic_process(
|
||||
@@ -265,7 +255,7 @@ struct basic_process
|
||||
{
|
||||
error_code ec;
|
||||
if (running(ec))
|
||||
wait(ec);
|
||||
process_handle_.wait(exit_status_, ec);
|
||||
if (ec)
|
||||
detail::throw_error(ec, "wait failed");
|
||||
return exit_code();
|
||||
@@ -287,8 +277,9 @@ struct basic_process
|
||||
return boost::exchange(process_handle_, get_executor());
|
||||
#endif
|
||||
}
|
||||
// Get the native
|
||||
/// Get the native
|
||||
native_handle_type native_handle() {return process_handle_.native_handle(); }
|
||||
/// Return the evaluated exit_code.
|
||||
int exit_code() const
|
||||
{
|
||||
return evaluate_exit_code(exit_status_);
|
||||
@@ -334,7 +325,7 @@ struct basic_process
|
||||
/** Note that this might be a process that already exited.*/
|
||||
bool is_open() const { return process_handle_.is_open(); }
|
||||
|
||||
/// Asynchronously wait for the process to exit and deliver the portable exit-code in the completion handler.
|
||||
/// Asynchronously wait for the process to exit and deliver the native exit-code in the completion handler.
|
||||
template <BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(void (error_code, int))
|
||||
WaitHandler BOOST_PROCESS_V2_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
|
||||
BOOST_PROCESS_V2_INITFN_AUTO_RESULT_TYPE(WaitHandler, void (error_code, int))
|
||||
|
||||
@@ -103,9 +103,15 @@ struct process_io_binding
|
||||
|
||||
|
||||
template<typename Executor>
|
||||
process_io_binding(BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_readable_pipe<Executor> & readable_pipe,
|
||||
typename std::enable_if<Target != STD_INPUT_HANDLE, Executor*>::type = 0)
|
||||
process_io_binding(BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_readable_pipe<Executor> & pipe)
|
||||
{
|
||||
if (Target == STD_INPUT_HANDLE)
|
||||
{
|
||||
auto h_ = pipe.native_handle();
|
||||
h = std::unique_ptr<void, handle_closer>{h_, get_flags(h_)};
|
||||
return ;
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::native_pipe_handle p[2];
|
||||
error_code ec;
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::create_pipe(p, ec);
|
||||
@@ -113,14 +119,19 @@ struct process_io_binding
|
||||
detail::throw_error(ec, "create_pipe");
|
||||
|
||||
h = std::unique_ptr<void, handle_closer>{p[1], true};
|
||||
readable_pipe.assign(p[0]);
|
||||
pipe.assign(p[0]);
|
||||
}
|
||||
|
||||
|
||||
template<typename Executor>
|
||||
process_io_binding(BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_writable_pipe<Executor> & writable_pipe,
|
||||
typename std::enable_if<Target == STD_INPUT_HANDLE, Executor*>::type = 0)
|
||||
process_io_binding(BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_writable_pipe<Executor> & pipe)
|
||||
{
|
||||
if (Target != STD_INPUT_HANDLE)
|
||||
{
|
||||
auto h_ = pipe.native_handle();
|
||||
h = std::unique_ptr<void, handle_closer>{h_, get_flags(h_)};
|
||||
return ;
|
||||
}
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::native_pipe_handle p[2];
|
||||
error_code ec;
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::create_pipe(p, ec);
|
||||
@@ -128,7 +139,7 @@ struct process_io_binding
|
||||
detail::throw_error(ec, "create_pipe");
|
||||
|
||||
h = std::unique_ptr<void, handle_closer>{p[0], true};
|
||||
writable_pipe.assign(p[1]);
|
||||
pipe.assign(p[1]);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -170,13 +181,19 @@ struct process_io_binding
|
||||
}
|
||||
|
||||
template<typename Executor>
|
||||
process_io_binding(BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_readable_pipe<Executor> & readable_pipe,
|
||||
typename std::enable_if<Target != STDIN_FILENO, Executor*>::type = 0)
|
||||
process_io_binding(BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_readable_pipe<Executor> & readable_pipe)
|
||||
{
|
||||
if (Target == STDIN_FILENO)
|
||||
{
|
||||
fd = readable_pipe.native_handle();
|
||||
return ;
|
||||
}
|
||||
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::native_pipe_handle p[2];
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::create_pipe(p, ec);
|
||||
if (ec)
|
||||
return ;
|
||||
detail::throw_error(ec, "create_pipe");
|
||||
|
||||
fd = p[1];
|
||||
if (::fcntl(p[0], F_SETFD, FD_CLOEXEC) == -1)
|
||||
{
|
||||
@@ -189,13 +206,20 @@ struct process_io_binding
|
||||
|
||||
|
||||
template<typename Executor>
|
||||
process_io_binding(BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_writable_pipe<Executor> & writable_pipe,
|
||||
typename std::enable_if<Target == STDIN_FILENO, Executor*>::type = 0)
|
||||
process_io_binding(BOOST_PROCESS_V2_ASIO_NAMESPACE::basic_writable_pipe<Executor> & writable_pipe)
|
||||
{
|
||||
|
||||
if (Target != STDIN_FILENO)
|
||||
{
|
||||
fd = writable_pipe.native_handle();
|
||||
return ;
|
||||
}
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::native_pipe_handle p[2];
|
||||
error_code ec;
|
||||
BOOST_PROCESS_V2_ASIO_NAMESPACE::detail::create_pipe(p, ec);
|
||||
if (ec)
|
||||
return ;
|
||||
detail::throw_error(ec, "create_pipe");
|
||||
|
||||
fd = p[0];
|
||||
if (::fcntl(p[1], F_SETFD, FD_CLOEXEC) == -1)
|
||||
{
|
||||
|
||||
@@ -37,7 +37,7 @@ struct as_user_launcher : default_launcher
|
||||
auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
asio::detail::throw_error(ec, "as_user_launcher");
|
||||
v2::detail::throw_error(ec, "as_user_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
@@ -68,7 +68,7 @@ struct as_user_launcher : default_launcher
|
||||
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
asio::detail::throw_error(ec, "as_user_launcher");
|
||||
detail::throw_error(ec, "as_user_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <boost/process/v2/cstring_ref.hpp>
|
||||
#include <boost/process/v2/detail/config.hpp>
|
||||
#include <boost/process/v2/detail/last_error.hpp>
|
||||
#include <boost/process/v2/detail/throw_error.hpp>
|
||||
#include <boost/process/v2/detail/utf8.hpp>
|
||||
#include <boost/process/v2/error.hpp>
|
||||
|
||||
@@ -244,7 +245,7 @@ struct default_launcher
|
||||
auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
asio::detail::throw_error(ec, "default_launcher");
|
||||
v2::detail::throw_error(ec, "default_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
@@ -275,7 +276,7 @@ struct default_launcher
|
||||
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
asio::detail::throw_error(ec, "default_launcher");
|
||||
detail::throw_error(ec, "default_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
@@ -311,7 +312,6 @@ struct default_launcher
|
||||
&startup_info.StartupInfo,
|
||||
&process_information);
|
||||
|
||||
auto ec__ = detail::get_last_error();
|
||||
if (ok == 0)
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace windows
|
||||
{
|
||||
if (wc == L'"')
|
||||
*(itr++) = L'\\';
|
||||
*(itr++) = wc;
|
||||
*(itr++) = wc;
|
||||
}
|
||||
|
||||
*(itr ++) = L'"';
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace windows
|
||||
/// A windows launcher using CreateProcessWithLogon instead of CreateProcess
|
||||
struct with_logon_launcher : default_launcher
|
||||
{
|
||||
std::wstring username, domain, password;
|
||||
std::wstring username, password, domain;
|
||||
DWORD logon_flags{0u};
|
||||
|
||||
with_logon_launcher(std::wstring username = L"",
|
||||
@@ -72,7 +72,7 @@ struct with_logon_launcher : default_launcher
|
||||
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
asio::detail::throw_error(ec, "with_logon_launcher");
|
||||
v2::detail::throw_error(ec, "with_logon_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ struct with_token_launcher : default_launcher
|
||||
auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
asio::detail::throw_error(ec, "with_token_launcher");
|
||||
v2::detail::throw_error(ec, "with_token_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
@@ -69,7 +69,7 @@ struct with_token_launcher : default_launcher
|
||||
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
|
||||
|
||||
if (ec)
|
||||
asio::detail::throw_error(ec, "with_token_launcher");
|
||||
detail::throw_error(ec, "with_token_launcher");
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ BOOST_AUTO_TEST_CASE(wait_group_test_timeout, *boost::unit_test::timeout(15))
|
||||
|
||||
bp::child c2(
|
||||
master_test_suite().argv[1],
|
||||
"--wait", "4",
|
||||
"--wait", "5",
|
||||
g,
|
||||
ec
|
||||
);
|
||||
|
||||
@@ -97,7 +97,8 @@ BOOST_AUTO_TEST_CASE(leak_test, *boost::unit_test::timeout(5))
|
||||
|
||||
#if defined( BOOST_WINDOWS_API )
|
||||
std::thread thr([]{});
|
||||
BOOST_CHECK(!bt::is_stream_handle(thr.native_handle(), ec)); BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
BOOST_CHECK(!bt::is_stream_handle(::GetCurrentProcess(), ec));
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
thr.join();
|
||||
#else
|
||||
# if defined(TFD_CLOEXEC) //check timer
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <iterator>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <thread>
|
||||
#if defined(BOOST_POSIX_API)
|
||||
# include <boost/lexical_cast.hpp>
|
||||
# include <boost/iostreams/device/file_descriptor.hpp>
|
||||
@@ -148,7 +149,8 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
else if (vm["loop"].as<bool>())
|
||||
{
|
||||
while (true);
|
||||
while (true)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
else if (vm["abort"].as<bool>())
|
||||
{
|
||||
|
||||
@@ -24,15 +24,6 @@ namespace bp = boost::process;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(terminate_set_on_error, *boost::unit_test::timeout(5))
|
||||
{
|
||||
std::atomic<bool> done{false};
|
||||
std::thread thr{
|
||||
[&]
|
||||
{
|
||||
for (int i = 0; i < 50 && !done.load(); i++)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
BOOST_REQUIRE(done.load());
|
||||
}};
|
||||
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
std::error_code ec;
|
||||
bp::child c(
|
||||
@@ -44,31 +35,14 @@ BOOST_AUTO_TEST_CASE(terminate_set_on_error, *boost::unit_test::timeout(5))
|
||||
|
||||
BOOST_CHECK(c.valid());
|
||||
BOOST_CHECK(c.running(ec));
|
||||
|
||||
BOOST_CHECK(!c.wait_for(std::chrono::milliseconds(100), ec));
|
||||
BOOST_CHECK(c.running(ec));
|
||||
BOOST_CHECK(c.valid());
|
||||
|
||||
c.terminate(ec);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(25));
|
||||
BOOST_CHECK(!c.running(ec));
|
||||
BOOST_CHECK(!ec);
|
||||
|
||||
done.store(true);
|
||||
thr.join();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(terminate_throw_on_error, *boost::unit_test::timeout(5))
|
||||
{
|
||||
std::atomic<bool> done{false};
|
||||
std::thread thr{
|
||||
[&]
|
||||
{
|
||||
for (int i = 0; i < 50 && !done.load(); i++)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
BOOST_REQUIRE(done.load());
|
||||
}};
|
||||
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
std::error_code ec;
|
||||
@@ -79,17 +53,10 @@ BOOST_AUTO_TEST_CASE(terminate_throw_on_error, *boost::unit_test::timeout(5))
|
||||
ec
|
||||
);
|
||||
BOOST_REQUIRE(!ec);
|
||||
|
||||
BOOST_CHECK(c.valid());
|
||||
BOOST_CHECK(c.running());
|
||||
|
||||
BOOST_CHECK(!c.wait_for(std::chrono::milliseconds(100), ec));
|
||||
BOOST_CHECK(c.running(ec));
|
||||
BOOST_CHECK(c.valid());
|
||||
|
||||
c.terminate();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(25));
|
||||
BOOST_CHECK(!c.running());
|
||||
|
||||
done.store(true);
|
||||
thr.join();
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ if [ os.name ] = NT
|
||||
lib Advapi32 ;
|
||||
lib Ntdll ;
|
||||
lib user32 ;
|
||||
lib Bcrypt ;
|
||||
}
|
||||
|
||||
project : requirements
|
||||
@@ -29,6 +30,7 @@ project : requirements
|
||||
<target-os>bsd:<linkflags>-lkvm
|
||||
<os>NT,<toolset>cw:<library>ws2_32
|
||||
<os>NT,<toolset>gcc:<library>ws2_32
|
||||
<os>NT,<toolset>gcc:<library>Bcrypt
|
||||
<define>BOOST_PROCESS_V2_SEPARATE_COMPILATION=1
|
||||
;
|
||||
|
||||
|
||||
@@ -62,7 +62,8 @@ BOOST_AUTO_TEST_CASE(environment)
|
||||
ec.clear();
|
||||
|
||||
for (auto && ke : bpe::current())
|
||||
BOOST_CHECK_EQUAL(bpe::get(std::get<0>(ke)), std::get<1>(ke));
|
||||
if (!std::get<1>(ke).empty())
|
||||
BOOST_CHECK_EQUAL(bpe::get(std::get<0>(ke)), std::get<1>(ke));
|
||||
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
@@ -150,7 +151,11 @@ BOOST_AUTO_TEST_CASE(wenvironment)
|
||||
BOOST_CHECK(ec);
|
||||
|
||||
for (const auto ke : bpe::current())
|
||||
{
|
||||
std::string key = std::get<0>(ke).string();
|
||||
if (!std::get<1>(ke).empty())
|
||||
BOOST_CHECK_EQUAL(bpe::get(std::get<0>(ke)), std::get<1>(ke));
|
||||
}
|
||||
|
||||
#if defined(BOOST_PROCESS_V2_WINDOWS)
|
||||
BOOST_CHECK_EQUAL(bpe::key(L"FOO"), bpe::key_view(L"Foo"));
|
||||
|
||||
@@ -24,8 +24,6 @@ BOOST_AUTO_TEST_CASE(test_pid)
|
||||
BOOST_CHECK_GT(all.size(), 0u);
|
||||
BOOST_CHECK(itr != all.end());
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(child_pid)
|
||||
@@ -34,12 +32,12 @@ BOOST_AUTO_TEST_CASE(child_pid)
|
||||
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
const auto pth = bp2::filesystem::absolute(master_test_suite().argv[1]);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
auto cs = bp2::child_pids(bp2::current_pid());
|
||||
boost::asio::io_context ctx;
|
||||
bp2::process proc(ctx, pth, {"sleep", "50000"});
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
bp2::process proc(ctx, pth, {"loop"});
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
auto c2 = bp2::child_pids(bp2::current_pid());
|
||||
BOOST_CHECK_LT(cs.size(), c2.size());
|
||||
BOOST_CHECK(std::find(cs.begin(), cs.end(), proc.id()) == cs.end());
|
||||
|
||||
@@ -167,7 +167,7 @@ BOOST_AUTO_TEST_CASE(request_exit)
|
||||
asio::writable_pipe wp{ctx};
|
||||
asio::connect_pipe(rp, wp);
|
||||
|
||||
bpv::process proc(ctx, sh, {}, bpv::process_stdio{wp}
|
||||
bpv::process proc(ctx, sh, {}, bpv::process_stdio{rp}
|
||||
#if defined(ASIO_WINDOWS)
|
||||
, asio::windows::show_window_minimized_not_active
|
||||
#endif
|
||||
@@ -371,27 +371,26 @@ BOOST_AUTO_TEST_CASE(popen)
|
||||
|
||||
asio::io_context ctx;
|
||||
|
||||
asio::readable_pipe rp{ctx};
|
||||
|
||||
|
||||
// default CWD
|
||||
bpv::popen proc(/*bpv::default_process_launcher(), */ctx, pth, {"echo"});
|
||||
|
||||
asio::write(proc, asio::buffer("FOOBAR"));
|
||||
BOOST_CHECK_EQUAL(asio::write(proc, asio::buffer("FOOBAR", 6)), 6);
|
||||
|
||||
proc.get_stdin().close();
|
||||
|
||||
std::string res;
|
||||
boost::system::error_code ec;
|
||||
std::size_t n = asio::read(proc, asio::dynamic_buffer(res), ec);
|
||||
while (ec == asio::error::interrupted)
|
||||
n += asio::read(rp, asio::dynamic_buffer(res), ec);
|
||||
n += asio::read(proc, asio::dynamic_buffer(res), ec);
|
||||
|
||||
BOOST_CHECK_MESSAGE(ec == asio::error::eof || ec == asio::error::broken_pipe, ec.message());
|
||||
BOOST_CHECK_MESSAGE(ec == asio::error::eof
|
||||
|| ec == asio::error::broken_pipe,
|
||||
ec.message());
|
||||
BOOST_REQUIRE_GE(n, 1u);
|
||||
// remove EOF
|
||||
res.pop_back();
|
||||
BOOST_CHECK_EQUAL(res, "FOOBAR");
|
||||
|
||||
proc.get_stdin().close();
|
||||
proc.wait();
|
||||
BOOST_CHECK_MESSAGE(proc.exit_code() == 0, proc.exit_code());
|
||||
}
|
||||
@@ -520,13 +519,34 @@ BOOST_AUTO_TEST_CASE(exit_code_as_error)
|
||||
|
||||
proc3.terminate();
|
||||
|
||||
proc1.async_wait(bpv::code_as_error([&](bpv::error_code ec){called ++; BOOST_CHECK(!ec);}));
|
||||
proc2.async_wait(bpv::code_as_error([&](bpv::error_code ec){called ++; BOOST_CHECK_MESSAGE(ec, ec.message());}));
|
||||
proc3.async_wait(bpv::code_as_error([&](bpv::error_code ec){called ++; BOOST_CHECK_MESSAGE(ec, ec.message());}));
|
||||
|
||||
proc1.async_wait(
|
||||
[&](bpv::error_code ec, int)
|
||||
{
|
||||
called ++;
|
||||
bpv::check_exit_code(ec, proc1.native_exit_code());
|
||||
BOOST_CHECK(!ec);
|
||||
});
|
||||
|
||||
proc2.async_wait(
|
||||
[&](bpv::error_code ec, int)
|
||||
{
|
||||
called ++;
|
||||
bpv::check_exit_code(ec, proc2.native_exit_code());
|
||||
BOOST_CHECK_MESSAGE(ec, ec.message());
|
||||
});
|
||||
|
||||
proc3.async_wait(
|
||||
[&](bpv::error_code ec, int)
|
||||
{
|
||||
called ++;
|
||||
bpv::check_exit_code(ec, proc3.native_exit_code());
|
||||
BOOST_CHECK_MESSAGE(ec, ec.message());
|
||||
});
|
||||
|
||||
|
||||
ctx.run();
|
||||
BOOST_CHECK_EQUAL(called, 3);
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(bind_launcher)
|
||||
@@ -537,17 +557,13 @@ BOOST_AUTO_TEST_CASE(bind_launcher)
|
||||
asio::io_context ctx;
|
||||
|
||||
asio::readable_pipe rp{ctx};
|
||||
asio::writable_pipe wp{ctx};
|
||||
asio::connect_pipe(rp, wp);
|
||||
|
||||
auto target = bpv::filesystem::canonical(bpv::filesystem::temp_directory_path());
|
||||
|
||||
auto l = bpv::bind_default_launcher(bpv::process_start_dir(target));
|
||||
|
||||
std::vector<std::string> args = {"print-cwd"};
|
||||
// default CWD
|
||||
bpv::process proc = l(ctx, pth, args, bpv::process_stdio{/*.in=*/{}, /*.out=*/wp});
|
||||
wp.close();
|
||||
bpv::process proc = l(ctx, pth, args, bpv::process_stdio{/*.in=*/{}, /*.out=*/rp});
|
||||
|
||||
std::string out;
|
||||
bpv::error_code ec;
|
||||
@@ -556,8 +572,8 @@ BOOST_AUTO_TEST_CASE(bind_launcher)
|
||||
while (ec == asio::error::interrupted)
|
||||
sz += asio::read(rp, asio::dynamic_buffer(out), ec);
|
||||
|
||||
BOOST_CHECK(sz != 0);
|
||||
BOOST_CHECK_MESSAGE((ec == asio::error::broken_pipe) || (ec == asio::error::eof), ec.message());
|
||||
BOOST_REQUIRE(sz != 0);
|
||||
|
||||
if (out.back() != '/' && target.string().back() == '/')
|
||||
out += '/';
|
||||
|
||||
Reference in New Issue
Block a user