2
0
mirror of https://github.com/boostorg/process.git synced 2026-01-19 16:32:15 +00:00

Compare commits

...

27 Commits

Author SHA1 Message Date
Klemens Morgenstern
9ed2fef8cd Fixed wrong type in probe_on_error on windows.
Closes #491.
2025-05-24 09:40:16 +08:00
Klemens Morgenstern
cd1621b197 fixed major resume/suspend typo
Closes #481.
2025-04-28 23:57:20 +08:00
Klemens Morgenstern
1baccf76cd pipe bindings use a type_trait. 2025-04-15 00:31:56 +08:00
Klemens Morgenstern
06595a2070 added BOOST_PROCESS_V2_DISABLE_SIGNALSET option 2025-04-14 23:55:23 +08:00
Klemens Morgenstern
7e712985c1 added BOOST_PROCESS_V2_PIPEFORK option 2025-04-14 23:55:23 +08:00
Klemens Morgenstern
da08060021 Set ENOTSUP when PROC_PPID_ONLY is undefined
closes #452
2025-04-14 23:54:14 +08:00
Klemens Morgenstern
afdbab734e Removed char_count
Closes #473
2025-04-14 23:53:30 +08:00
Klemens Morgenstern
9dcd1a2775 added duplication check for SIGINFO
Closes #474
2025-04-14 23:51:35 +08:00
Osyotr
5756891558 Fix wide strings conversion on POSIX
This commit effectively reverts #179 which shouldn't have been merged in the first place. See https://github.com/boostorg/filesystem/pull/163#issuecomment-786794483 for more info.
2025-04-14 23:49:00 +08:00
RK-BFX
1d6c9ed0ec Fix conflicting pipe name in independent plug-in DLLs
Include numerical representation of local static variable's address into the pipe name to discriminate Boost.Process instances in independent DLLs.

Fixes #476

Also (auto-)remove excessive concurrent empty lines.
2025-04-14 23:48:00 +08:00
Yury Bura
a941c8e89c Add BOOST_PROCESS_USE_STD_FS option 2025-04-14 23:46:36 +08:00
Klemens Morgenstern
89d2cc325a Update index.html
Fixes #479
2025-04-11 23:31:02 +08:00
js-nano
e637f8483d Fix up usage of std::move_backward
The destinations should point to the *end* of the destination range

https://en.cppreference.com/w/cpp/algorithm/move_backward
2025-03-06 17:39:28 +08:00
Klemens Morgenstern
94aa3b6b43 fixed environ for OSX
closes #453
2025-02-27 10:13:22 +08:00
Klemens Morgenstern
d7df711628 remove :: from dirfd
closes #461
2025-02-27 10:12:55 +08:00
SimonMaracine
8ae055bfbd Remove optional dependency on filesystem when not meant to be
Build previously failed when BOOST_PROCESS_USE_STD_FS was ON, because filesystem was linked to regardless.
2025-02-21 08:09:42 +08:00
Jonas Greitemann
ab28b511a9 fix v1 tests after v2 became the default
As of 2ccd97cd48, v2 is the default when using the unversioned includes.
This broke the v1 tests which were still using those.
2025-02-21 08:08:36 +08:00
SimonMaracine
529fb1e222 Fix include directives from boost/process/posix/*.hpp having wrong paths 2025-02-21 08:08:17 +08:00
Jens Diewald
d534ed6c34 Fix small yet confusing Typo in Doc 2025-02-05 19:27:55 +08:00
Dirk Stolle
bb375f50bd Fix several typos 2025-01-23 07:45:16 +08:00
Dirk Stolle
c329e05fb6 chore: remove executable flags from .cpp files
See <https://github.com/boostorg/admin/issues/47#issuecomment-2575165830>.

[ci skip]
2025-01-21 21:55:11 +08:00
Ryan Zoeller
b781b49a97 doc: fix typo in stdio 2025-01-21 07:40:31 +08:00
Klemens Morgenstern
a2d2753aa8 zombie process fixes
closes #445, #447
2025-01-13 09:31:48 +08:00
Klemens Morgenstern
1b5272a9e1 changed cwd comparison to equivalent. 2025-01-13 08:36:36 +08:00
Jonas Greitemann
e842a060f1 implement move operations for process_io_binding and delete copy operations
This makes the test added in the previous commit pass.
2025-01-13 08:13:33 +08:00
Jonas Greitemann
4bb842564f add a (failing) test for process_stdio move semantics
This test currently fails on POSIX, as `process_io_binding` does not
explicitly implement move operations but holds on to a file descriptor
which exhibits reference semantics and has a non-trivial destructor.

The same test should pass on Windows as the Windows implementation makes
use of `unique_ptr` which gives it correct move semantics by virtue of
the rule of zero.
2025-01-13 08:13:33 +08:00
Jonas Greitemann
359820097b add test case for initializing process_stdio with complementary pipe ends
`process_stdio` holds on to the handles for `in`/`out`/`err`. In case of
pipes, `in` needs the handles of a `readable_pipe`, whereas `out` and
`err` need the handles of `writable_pipe`s. So far, the tests all create
a new pair using `connect_pipe`, pass the "correct" end into
`process_stdio`, and use the other end to interface with the process.

However, `process_io_binding` also supports construction from the
complementary pipe types, i.e., constructing `in`'s binding from a
`writable_pipe` and `out`/`err`'s bindings from `readable_pipe`s.
In this case, the constructor will create the corresponding pipe itself
and keep ownership of it. This mode was thus far not tested.
2025-01-13 08:13:33 +08:00
106 changed files with 744 additions and 267 deletions

View File

@@ -7,6 +7,8 @@ cmake_minimum_required(VERSION 3.5...3.16)
project(boost_process VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
option(BOOST_PROCESS_USE_STD_FS "Use std::filesystem instead of Boost.Filesystem" OFF)
add_library(boost_process
src/detail/environment_posix.cpp
src/detail/environment_win.cpp
@@ -35,7 +37,6 @@ target_link_libraries(boost_process
Boost::asio
Boost::config
Boost::core
Boost::filesystem
Boost::fusion
Boost::iterator
Boost::move
@@ -50,13 +51,14 @@ target_compile_definitions(boost_process
PRIVATE BOOST_PROCESS_SOURCE=1
)
if (BOOST_PROCESS_USE_STD_FS)
target_compile_definitions(boost_process PUBLIC BOOST_PROCESS_USE_STD_FS=1 )
if(BOOST_PROCESS_USE_STD_FS)
target_compile_definitions(boost_process PUBLIC BOOST_PROCESS_USE_STD_FS)
target_compile_features(boost_process PUBLIC cxx_std_17)
else()
target_link_libraries(boost_process PUBLIC Boost::filesystem)
endif()
if (WIN32)
if(WIN32)
target_link_libraries(boost_process PUBLIC ntdll shell32 advapi32 user32 ws2_32)
endif()

View File

@@ -7,5 +7,5 @@ Boost process v2 can be configured in the following ways:
| Macro | Description
| `BOOST_PROCESS_V2_STANDALONE` | Build boost.process for standalone asio
| `BOOST_PROCESS_USE_STD_FS` | Use std::filesystem instead of boost::filsystem
| `BOOST_PROCESS_USE_STD_FS` | Use std::filesystem instead of boost::filesystem
| `BOOST_PROCESS_V2_POSIX_FORCE_DISABLE_CLOSE_RANGE` | Disable usage of `close_range`.

View File

@@ -9,7 +9,7 @@ template<typename Launcher, typename ... Init>
auto bind_launcher(Launcher && launcher, Init && ... init);
// Calls bind_launcher with the default_launcher as the first parameter.
// The new launcher with bound paramaters
// The new launcher with bound parameters
template<typename ... Init>
auto bind_default_launcher(Init && ... init);
----

View File

@@ -25,13 +25,13 @@ namespace environment
* Windows treats keys as case-insensitive yet perserving. The char traits are made to reflect
* that behaviour.
*/
tempalte<typename Char>
template<typename Char>
using key_char_traits = implementation_defined ;
// A char traits type that reflects the OS rules for string representing environment values.
/* Can be an alias of std::char_traits. May only be defined for `char` and `wchar_t`.
*/
tempalte<typename Char>
template<typename Char>
using value_char_traits = implementation_defined ;
// The character type used by the environment. Either `char` or `wchar_t`.

View File

@@ -2,7 +2,7 @@
[#process_handle]
A process handle is an unmanaged version of a process.
This means it does not terminate the proces on destruction and
This means it does not terminate the process on destruction and
will not keep track of the exit-code.
NOTE: that the exit code might be discovered early, during a call to `running`.

View File

@@ -16,7 +16,7 @@ automatically connected and the other side will get assigned to the child proces
include::../example/stdio.cpp[tag=readable_pipe]
----
readable pipes can be assigned to `out` an `err`, while writable_pipes can be assigned to `in`.
readable pipes can be assigned to `out` and `err`, while writable_pipes can be assigned to `in`.
== `FILE*`

View File

@@ -64,7 +64,7 @@ This concerns especially the `wait_for` and `wait_until` functions on the proces
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,
a wait_for can not safely be implemented with an async_wait + timeout.
a wait_for can now safely be implemented with an async_wait + timeout.
== UTF-8

View File

@@ -1 +1 @@
#include <boost/process/v2/bind_fd.hpp>
#include <boost/process/v2/posix/bind_fd.hpp>

View File

@@ -1 +1 @@
#include <boost/process/v2/default_launcher.hpp>
#include <boost/process/v2/posix/default_launcher.hpp>

View File

@@ -1 +1 @@
#include <boost/process/v2/fork_and_forget_launcher.hpp>
#include <boost/process/v2/posix/fork_and_forget_launcher.hpp>

View File

@@ -1 +1 @@
#include <boost/process/v2/pdfork_launcher.hpp>
#include <boost/process/v2/posix/pdfork_launcher.hpp>

View File

@@ -1 +1 @@
#include <boost/process/v2/vfork_launcher.hpp>
#include <boost/process/v2/posix/vfork_launcher.hpp>

View File

@@ -39,7 +39,7 @@ child::child(Args&&...args)
typedef ::boost::process::v1::detail::api::pid_t pid_t;
#if defined(BOOST_PROCESS_DOXYGEN)
/** The main class to hold a child process. It is simliar to [std::thread](http://en.cppreference.com/w/cpp/thread/thread),
/** The main class to hold a child process. It is similar to [std::thread](http://en.cppreference.com/w/cpp/thread/thread),
* in that it has a join and detach function.
*
* @attention The destructor will call terminate on the process if not joined or detached without any warning.

View File

@@ -107,7 +107,7 @@ public:
using string_type = std::basic_string<char_type>;
using native_handle_type = char_type **;
void reload() {this->_env_impl = ::environ;}
void reload() {this->_env_impl = environ;}
string_type get(const pointer_type id) { return getenv(id); }
void set(const pointer_type id, const pointer_type value)
@@ -136,7 +136,7 @@ public:
native_environment_impl & operator=(native_environment_impl && ) = default;
native_handle_type _env_impl = environ;
native_handle_type native_handle() const {return ::environ;}
native_handle_type native_handle() const {return environ;}
};

View File

@@ -275,7 +275,7 @@ class executor
prepare_cmd_style_fn = exe;
if ((prepare_cmd_style_fn.find('/') == std::string::npos) && ::access(prepare_cmd_style_fn.c_str(), X_OK))
{
const auto * e = ::environ;
const auto * e = environ;
while ((e != nullptr) && (*e != nullptr) && !boost::starts_with(*e, "PATH="))
e++;
@@ -316,7 +316,7 @@ public:
const char * exe = nullptr;
char *const* cmd_line = nullptr;
bool cmd_style = false;
char **env = ::environ;
char **env = environ;
pid_t pid = -1;
std::shared_ptr<std::atomic<int>> exit_status = std::make_shared<std::atomic<int>>(still_active);

View File

@@ -31,6 +31,8 @@ inline std::string make_pipe_name()
static std::atomic_size_t cnt{0};
name += std::to_string(pid);
name += "_";
name += std::to_string(intptr_t(&cnt)); // to unclash Boost instances in plug-in DLLs
name += "_";
name += std::to_string(cnt++);
return name;
@@ -60,8 +62,6 @@ public:
async_pipe(boost::asio::io_context & ios_source, boost::asio::io_context & ios_sink, const std::string & name)
: async_pipe(ios_source, ios_sink, name, false) {}
inline async_pipe(const async_pipe& rhs);
async_pipe(async_pipe&& rhs) : _source(std::move(rhs._source)), _sink(std::move(rhs._sink))
{
@@ -153,7 +153,6 @@ public:
return _sink.write_some(buffers);
}
template<typename MutableBufferSequence>
std::size_t read_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept
{
@@ -281,7 +280,6 @@ async_pipe::async_pipe(const async_pipe& p) :
_sink. assign(sink);
}
async_pipe::async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & ios_sink,
const std::string & name, bool private_) : _source(ios_source), _sink(ios_sink)
@@ -298,7 +296,6 @@ async_pipe::async_pipe(boost::asio::io_context & ios_source,
| FILE_FLAG_OVERLAPPED_, //write flag
0, private_ ? 1 : ::boost::winapi::PIPE_UNLIMITED_INSTANCES_, 8192, 8192, 0, nullptr);
if (source == boost::winapi::INVALID_HANDLE_VALUE_)
::boost::process::v1::detail::throw_last_error("create_named_pipe(" + name + ") failed");

View File

@@ -222,7 +222,7 @@ basic_environment_impl<Char>::basic_environment_impl(const native_environment_im
while ((*p != null_char<Char>()) || (*(p+1) != null_char<Char>()))
p++;
p++; //pointing to the second nullchar
p++; //to get the pointer behing the second nullchar, so it's end.
p++; //to get the pointer behind the second nullchar, so it's end.
this->_data.assign(beg, p);
this->reload();

View File

@@ -627,7 +627,7 @@ public:
using base_type::operator=;
};
///Type definition to hold a seperate environment.
///Type definition to hold a separate environment.
template<typename Char>
class basic_environment : public basic_environment_impl<Char, detail::api::basic_environment_impl>
{
@@ -646,10 +646,10 @@ typedef basic_native_environment<char> native_environment;
typedef basic_native_environment<wchar_t> wnative_environment;
#if !defined(BOOST_NO_ANSI_APIS)
///Type definition to hold a seperate environment.
///Type definition to hold a separate environment.
typedef basic_environment<char> environment;
#endif
///Type definition to hold a seperate environment.
///Type definition to hold a separate environment.
typedef basic_environment<wchar_t> wenvironment;
}}
@@ -673,10 +673,10 @@ inline int get_id() { return ::boost::process::v1::detail::a
///Get the native handle of the current process.
inline native_handle_type native_handle() { return ::boost::process::v1::detail::api::native_handle();}
#if !defined(BOOST_NO_ANSI_APIS)
///Get the enviroment of the current process.
///Get the environment of the current process.
inline native_environment environment() { return ::boost::process::v1:: native_environment(); }
#endif
///Get the enviroment of the current process.
///Get the environment of the current process.
inline wnative_environment wenvironment() { return ::boost::process::v1::wnative_environment(); }
///Get the path environment variable of the current process runs.
inline std::vector<boost::process::v1::filesystem::path> path()

View File

@@ -124,7 +124,7 @@ struct handler
template <class Executor>
void on_setup(Executor&) const {}
/** This function is invoked if an error occured while trying to launch the process.
/** This function is invoked if an error occurred while trying to launch the process.
* \note It is not required to be const.
*/
template <class Executor>
@@ -136,7 +136,7 @@ struct handler
template <class Executor>
void on_success(Executor&) const {}
/**This function is invoked if an error occured during the call of `fork`.
/**This function is invoked if an error occurred during the call of `fork`.
* \note This function will only be called on posix.
*/
template<typename Executor>
@@ -249,7 +249,7 @@ struct posix_executor
///A pointer to the argument-vector.
char *const* cmd_line = nullptr;
///A pointer to the environment variables, as default it is set to [environ](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html)
char **env = ::environ;
char **env = environ;
///The pid of the process - it will be -1 before invoking [fork](http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html), and after forking either 0 for the new process or a positive value if in the current process. */
pid_t pid = -1;
///This shared-pointer holds the exit code. It's done this way, so it can be shared between an `asio::io_context` and \ref child.
@@ -335,7 +335,7 @@ struct windows_executor
void set_startup_info_ex();
///This element is an instance or a reference (if \ref startup_info_ex exists) to the [startup-info](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331.aspx) for the process.
startup_info_t startup_info;
///This element is the instance of the [extended startup-info](https://msdn.microsoft.com/de-de/library/windows/desktop/ms686329.aspx). It is only available with a winapi-version equal or highter than 6.
///This element is the instance of the [extended startup-info](https://msdn.microsoft.com/de-de/library/windows/desktop/ms686329.aspx). It is only available with a winapi-version equal or higher than 6.
startup_info_ex_t startup_info_ex;
};

View File

@@ -78,8 +78,9 @@ inline std::locale default_locale()
std::locale global_loc = std::locale();
return std::locale(global_loc, new std::codecvt_utf8<wchar_t>);
# else // Other POSIX
// Return a default locale object.
return std::locale();
// ISO C calls std::locale("") "the locale-specific native environment", and this
// locale is the default for many POSIX-based operating systems such as Linux.
return std::locale("");
# endif
}

View File

@@ -18,6 +18,8 @@
#else
#if defined(BOOST_PROCESS_V2_PDFORK)
#include <boost/process/v2/posix/pdfork_launcher.hpp>
#elif defined(BOOST_PROCESS_V2_PIPEFORK)
#include <boost/process/v2/posix/pipe_fork_launcher.hpp>
#else
#include <boost/process/v2/posix/default_launcher.hpp>
#endif
@@ -48,6 +50,8 @@ typedef windows::default_launcher default_process_launcher;
#else
#if defined(BOOST_PROCESS_V2_PDFORK)
typedef posix::pdfork_launcher default_process_launcher;
#elif defined(BOOST_PROCESS_V2_PIPEFORK)
typedef posix::pipe_fork_launcher default_process_launcher;
#else
typedef posix::default_launcher default_process_launcher;
#endif

View File

@@ -165,7 +165,7 @@ BOOST_PROCESS_V2_END_NAMESPACE
#include <sys/syscall.h>
#if defined(SYS_pidfd_open)
#if defined(SYS_pidfd_open) && !defined(BOOST_PROCESS_V2_DISABLE_PIDFD_OPEN)
#define BOOST_PROCESS_V2_PIDFD_OPEN 1
#define BOOST_PROCESS_V2_HAS_PROCESS_HANDLE 1
#endif

View File

@@ -14,8 +14,13 @@
#include <boost/process/v2/detail/config.hpp>
#include <boost/process/v2/cstring_ref.hpp>
#if defined(__APPLE__) || defined(__MACH__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__sun)
extern "C" { extern char **environ; }
#if defined(__APPLE__)
# include <crt_externs.h>
# if !defined(environ)
# define environ (*_NSGetEnviron())
# endif
#elif defined(__MACH__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__sun)
extern "C" { extern char **environ; }
#endif
BOOST_PROCESS_V2_BEGIN_NAMESPACE

View File

@@ -85,7 +85,7 @@ struct key_char_traits
if (s1 < s2)
return std::move(s2, s2 + n, s1);
else
return std::move_backward(s2, s2 + n, s1);
return std::move_backward(s2, s2 + n, s1 + n);
}
BOOST_CONSTEXPR static

View File

@@ -255,7 +255,7 @@ struct basic_process_handle_fd
ec.clear();
exit_code = code;
}
return false;
return false;
}
bool running(native_exit_code_type &exit_code)

View File

@@ -18,19 +18,27 @@
#if defined(BOOST_PROCESS_V2_STANDALONE)
#include <asio/any_io_executor.hpp>
#include <asio/append.hpp>
#include <asio/associated_immediate_executor.hpp>
#include <asio/compose.hpp>
#include <asio/dispatch.hpp>
#include <asio/posix/basic_stream_descriptor.hpp>
#include <asio/post.hpp>
#include <asio/windows/signal_set.hpp>
#if !defined(BOOST_PROCESS_V2_DISABLE_SIGNALSET)
#include <asio/signal_set.hpp>
#endif
#else
#include <boost/asio/any_io_executor.hpp>
#include <boost/asio/append.hpp>
#include <boost/asio/associated_immediate_executor.hpp>
#include <boost/asio/compose.hpp>
#include <boost/asio/dispatch.hpp>
#include <boost/asio/posix/basic_stream_descriptor.hpp>
#include <boost/asio/post.hpp>
#if !defined(BOOST_PROCESS_V2_DISABLE_SIGNALSET)
#include <boost/asio/signal_set.hpp>
#endif
#endif
BOOST_PROCESS_V2_BEGIN_NAMESPACE
@@ -45,7 +53,7 @@ struct basic_process_handle_fd_or_signal
typedef Executor executor_type;
executor_type get_executor()
{ return signal_set_.get_executor(); }
{ return descriptor_.get_executor(); }
/// Rebinds the process_handle to another executor.
template<typename Executor1>
@@ -277,14 +285,13 @@ struct basic_process_handle_fd_or_signal
int res = ::waitpid(pid_, &code, WNOHANG);
if (res == -1)
ec = get_last_error();
else
ec.clear();
if (process_is_running(res))
else if (res == 0)
return true;
else
{
ec.clear();
exit_code = code;
}
return false;
}
@@ -311,12 +318,19 @@ struct basic_process_handle_fd_or_signal
struct basic_process_handle_fd_or_signal;
pid_type pid_ = -1;
net::posix::basic_stream_descriptor<Executor> descriptor_;
#if !defined(BOOST_PROCESS_V2_DISABLE_SIGNALSET)
net::basic_signal_set<Executor> signal_set_{descriptor_.get_executor(), SIGCHLD};
#else
int signal_set_;
#endif
struct async_wait_op_
{
net::posix::basic_descriptor<Executor> &descriptor;
#if !defined(BOOST_PROCESS_V2_DISABLE_SIGNALSET)
net::basic_signal_set<Executor> &handle;
#else
int dummy;
#endif
pid_type pid_;
bool needs_post = true;
@@ -343,35 +357,41 @@ struct basic_process_handle_fd_or_signal
if (!ec && (wait_res == 0))
{
needs_post = false;
if (descriptor.is_open())
descriptor.async_wait(
net::posix::descriptor_base::wait_read,
std::move(self));
{
needs_post = false;
descriptor.async_wait(
net::posix::descriptor_base::wait_read,
std::move(self));
return;
}
else
handle.async_wait(std::move(self));
return;
{
#if !defined(BOOST_PROCESS_V2_DISABLE_SIGNALSET)
needs_post = false;
handle.async_wait(std::move(self));
return;
#else
BOOST_PROCESS_V2_ASSIGN_EC(ec, net::error::operation_not_supported);
#endif
}
}
struct completer
{
error_code ec;
native_exit_code_type code;
typename std::decay<Self>::type self;
void operator()()
{
self.complete(ec, code);
}
};
const auto exec = self.get_executor();
completer cpl{ec, exit_code, std::move(self)};
if (needs_post)
net::post(exec, std::move(cpl));
{
auto exec = net::get_associated_immediate_executor(self, descriptor.get_executor());
net::dispatch(exec, net::append(std::move(self), exit_code, ec));
}
else
net::dispatch(exec, std::move(cpl));
{
auto exec = net::get_associated_executor(self);
net::dispatch(exec, net::append(std::move(self), exit_code, ec));
}
}
template<typename Self>
void operator()(Self &&self, native_exit_code_type code, error_code ec)
{
self.complete(ec, code);
}
};
public:

View File

@@ -17,17 +17,25 @@
#if defined(BOOST_PROCESS_V2_STANDALONE)
#include <asio/any_io_executor.hpp>
#include <asio/append.hpp>
#include <asio/associated_immediate_executor.hpp>
#include <asio/compose.hpp>
#include <asio/dispatch.hpp>
#include <asio/post.hpp>
#if !defined(BOOST_PROCESS_V2_DISABLE_SIGNALSET)
#include <asio/signal_set.hpp>
#endif
#else
#include <boost/asio/any_io_executor.hpp>
#include <boost/asio/append.hpp>
#include <boost/asio/associated_immediate_executor.hpp>
#include <boost/asio/compose.hpp>
#include <boost/asio/dispatch.hpp>
#include <boost/asio/post.hpp>
#if !defined(BOOST_PROCESS_V2_DISABLE_SIGNALSET)
#include <boost/asio/signal_set.hpp>
#endif
#endif
BOOST_PROCESS_V2_BEGIN_NAMESPACE
@@ -86,9 +94,14 @@ struct basic_process_handle_signal
basic_process_handle_signal& operator=(basic_process_handle_signal && handle)
{
pid_ = handle.id();
#if !defined(BOOST_PROCESS_V2_DISABLE_SIGNALSET)
signal_set_.~basic_signal_set();
using ss = net::basic_signal_set<Executor>;
new (&signal_set_) ss(handle.get_executor(), SIGCHLD);
#else
signal_set_.executor = handle.signal_set_.executor;
#endif
handle.pid_ = -1;
return *this;
}
@@ -244,11 +257,13 @@ struct basic_process_handle_signal
int res = ::waitpid(pid_, &code, WNOHANG);
if (res == -1)
ec = get_last_error();
if (res == 0)
else if (res == 0)
return true;
else
{
ec.clear();
exit_code = code;
}
return false;
}
@@ -273,10 +288,24 @@ struct basic_process_handle_signal
template<typename>
friend struct basic_process_handle_signal;
pid_type pid_ = -1;
#if !defined(BOOST_PROCESS_V2_DISABLE_SIGNALSET)
net::basic_signal_set<Executor> signal_set_;
#else
struct signal_set_dummy_
{
signal_set_dummy_(signal_set_dummy_ &&) = default;
signal_set_dummy_(const signal_set_dummy_ &) = default;
Executor executor;
using executor_type = Executor;
executor_type get_executor() {return executor;}
signal_set_dummy_(Executor executor, int) : executor(std::move(executor)) {}
};
signal_set_dummy_ signal_set_;
#endif
struct async_wait_op_
{
#if !defined(BOOST_PROCESS_V2_DISABLE_SIGNALSET)
net::basic_signal_set<Executor> &handle;
pid_type pid_;
@@ -315,20 +344,25 @@ struct basic_process_handle_signal
return;
}
struct completer
{
error_code ec;
native_exit_code_type code;
typename std::decay<Self>::type self;
void operator()()
{
self.complete(ec, code);
}
};
const auto exec = self.get_executor();
net::dispatch(exec, completer{ec, exit_code, std::move(self)});
net::dispatch(exec, net::append(std::move(self), exit_code, ec));
}
#else
signal_set_dummy_ dummy_;
pid_t pid;
template<typename Self>
void operator()(Self &&self)
{
auto exec = net::get_associated_immediate_executor(self, dummy_.get_executor());
error_code ec;
BOOST_PROCESS_V2_ASSIGN_EC(ec, net::error::operation_not_supported);
net::dispatch(exec, net::append(std::move(self), native_exit_code_type(), ec));
}
#endif
template<typename Self>
void operator()(Self &&self, native_exit_code_type code, error_code ec)
{
self.complete(ec, code);
}
};
public:

View File

@@ -43,13 +43,13 @@ namespace environment
* Windows treats keys as case-insensitive yet perserving. The char traits are made to reflect
* that behaviour.
*/
tempalte<typename Char>
template<typename Char>
using key_char_traits = implementation_defined ;
/// A char traits type that reflects the OS rules for string representing environment values.
/** Can be an alias of std::char_traits. May only be defined for `char` and `wchar_t`.
*/
tempalte<typename Char>
template<typename Char>
using value_char_traits = implementation_defined ;
/// The character type used by the environment. Either `char` or `wchar_t`.

View File

@@ -26,11 +26,17 @@
#endif
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#if defined(__APPLE__) || defined(__MACH__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__sun)
extern "C" { extern char **environ; }
#if defined(__APPLE__)
# include <crt_externs.h>
# if !defined(environ)
# define environ (*_NSGetEnviron())
# endif
#elif defined(__MACH__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__sun)
extern "C" { extern char **environ; }
#endif
BOOST_PROCESS_V2_BEGIN_NAMESPACE
@@ -96,7 +102,7 @@ template<typename Launcher, typename Init>
inline auto invoke_on_error(Launcher & launcher, const filesystem::path &executable,
const char * const * (&cmd_line),
const error_code & ec, Init && init, derived && )
-> decltype(init.on_error(launcher, ec, executable, cmd_line, ec))
-> decltype(init.on_error(launcher, executable, cmd_line, ec))
{
init.on_error(launcher, executable, cmd_line, ec);
}
@@ -160,7 +166,7 @@ template<typename Launcher, typename Init>
inline auto invoke_on_fork_error(Launcher & launcher, const filesystem::path &executable,
const char * const * (&cmd_line),
const error_code & ec, Init && init, derived && )
-> decltype(init.on_fork_error(launcher, ec, executable, cmd_line, ec))
-> decltype(init.on_fork_error(launcher, executable, cmd_line, ec))
{
init.on_fork_error(launcher, executable, cmd_line, ec);
}
@@ -182,41 +188,6 @@ inline void on_fork_error(Launcher & launcher, const filesystem::path &executabl
on_fork_error(launcher, executable, cmd_line, ec, inits...);
}
template<typename Launcher, typename Init>
inline void invoke_on_fork_success(Launcher & /*launcher*/, const filesystem::path &/*executable*/,
const char * const * (&/*cmd_line*/),
Init && /*init*/, base && )
{
}
template<typename Launcher, typename Init>
inline auto invoke_on_fork_success(Launcher & launcher, const filesystem::path &executable,
const char * const * (&cmd_line),
Init && init, derived && )
-> decltype(init.on_fork_success(launcher, executable, cmd_line))
{
init.on_fork_success(launcher, executable, cmd_line);
}
template<typename Launcher>
inline void on_fork_success(Launcher & /*launcher*/, const filesystem::path &/*executable*/,
const char * const * (&/*cmd_line*/))
{
}
template<typename Launcher, typename Init1, typename ... Inits>
inline void on_fork_success(Launcher & launcher, const filesystem::path &executable,
const char * const * (&cmd_line),
Init1 && init1, Inits && ... inits)
{
invoke_on_fork_success(launcher, executable, cmd_line, init1, derived{});
on_fork_success(launcher, executable, cmd_line, inits...);
}
template<typename Launcher, typename Init>
inline error_code invoke_on_exec_setup(Launcher & /*launcher*/, const filesystem::path &/*executable*/,
const char * const * (&/*cmd_line*/),
@@ -266,7 +237,7 @@ template<typename Launcher, typename Init>
inline auto invoke_on_exec_error(Launcher & launcher, const filesystem::path &executable,
const char * const * (&cmd_line),
const error_code & ec, Init && init, derived && )
-> decltype(init.on_exec_error(launcher, ec, executable, cmd_line, ec))
-> decltype(init.on_exec_error(launcher, executable, cmd_line, ec))
{
init.on_exec_error(launcher, executable, cmd_line, ec);
}
@@ -293,7 +264,7 @@ inline void on_exec_error(Launcher & launcher, const filesystem::path &executabl
struct default_launcher
{
/// The pointer to the environment forwarded to the subprocess.
const char * const * env = ::environ;
const char * const * env = environ;
/// The pid of the subprocess - will be assigned after fork.
int pid = -1;
@@ -440,6 +411,7 @@ struct default_launcher
if (ec)
{
detail::on_error(*this, executable, argv, ec, inits...);
do { ::waitpid(pid, nullptr, 0); } while (errno == EINTR);
return basic_process<Executor>{exec};
}
}

View File

@@ -124,6 +124,7 @@ struct fork_and_forget_launcher : default_launcher
if (ec)
{
detail::on_error(*this, executable, argv, ec, inits...);
do { ::waitpid(pid, nullptr, 0); } while (errno == EINTR);
return basic_process<Executor>{exec};
}
}

View File

@@ -161,6 +161,7 @@ struct pdfork_launcher : default_launcher
if (ec)
{
detail::on_error(*this, executable, argv, ec, inits...);
do { ::waitpid(pid, nullptr, 0); } while (errno == EINTR);
return basic_process<Executor>{exec};
}
}

View File

@@ -0,0 +1,185 @@
// Copyright (c) 2022 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_V2_POSIX_PIPE_FORK_LAUNCHER_HPP
#define BOOST_PROCESS_V2_POSIX_PIPE_FORK_LAUNCHER_HPP
#include <boost/process/v2/posix/default_launcher.hpp>
#include <unistd.h>
BOOST_PROCESS_V2_BEGIN_NAMESPACE
namespace posix
{
/// A launcher using `pipe_fork`. Default on FreeBSD
struct pipe_fork_launcher : default_launcher
{
/// The file descriptor of the subprocess. Set after fork.
pipe_fork_launcher() = default;
template<typename ExecutionContext, typename Args, typename ... Inits>
auto operator()(ExecutionContext & context,
const typename std::enable_if<is_convertible<
ExecutionContext&, net::execution_context&>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
{
error_code ec;
auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
if (ec)
v2::detail::throw_error(ec, "pipe_fork_launcher");
return proc;
}
template<typename ExecutionContext, typename Args, typename ... Inits>
auto operator()(ExecutionContext & context,
error_code & ec,
const typename std::enable_if<is_convertible<
ExecutionContext&, net::execution_context&>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
{
return (*this)(context.get_executor(), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
}
template<typename Executor, typename Args, typename ... Inits>
auto operator()(Executor exec,
const typename std::enable_if<
net::execution::is_executor<Executor>::value ||
net::is_executor<Executor>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> basic_process<Executor>
{
error_code ec;
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
if (ec)
v2::detail::throw_error(ec, "pipe_fork_launcher");
return proc;
}
template<typename Executor, typename Args, typename ... Inits>
auto operator()(Executor exec,
error_code & ec,
const typename std::enable_if<
net::execution::is_executor<Executor>::value ||
net::is_executor<Executor>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> basic_process<Executor>
{
auto argv = this->build_argv_(executable, std::forward<Args>(args));
int fd = -1;
{
pipe_guard pg, pg_wait;
if (::pipe(pg.p))
{
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category());
return basic_process<Executor>{exec};
}
if (::fcntl(pg.p[1], F_SETFD, FD_CLOEXEC))
{
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category());
return basic_process<Executor>{exec};
}
if (::pipe(pg_wait.p))
{
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category());
return basic_process<Executor>{exec};
}
if (::fcntl(pg_wait.p[1], F_SETFD, FD_CLOEXEC))
{
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category());
return basic_process<Executor>{exec};
}
ec = detail::on_setup(*this, executable, argv, inits ...);
if (ec)
{
detail::on_error(*this, executable, argv, ec, inits...);
return basic_process<Executor>(exec);
}
fd_whitelist.push_back(pg.p[1]);
fd_whitelist.push_back(pg_wait.p[1]);
auto & ctx = net::query(
exec, net::execution::context);
ctx.notify_fork(net::execution_context::fork_prepare);
pid = ::fork();
if (pid == -1)
{
ctx.notify_fork(net::execution_context::fork_parent);
detail::on_fork_error(*this, executable, argv, ec, inits...);
detail::on_error(*this, executable, argv, ec, inits...);
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category());
return basic_process<Executor>{exec};
}
else if (pid == 0)
{
ctx.notify_fork(net::execution_context::fork_child);
::close(pg.p[0]);
ec = detail::on_exec_setup(*this, executable, argv, inits...);
if (!ec)
{
close_all_fds(ec);
}
if (!ec)
::execve(executable.c_str(), const_cast<char * const *>(argv), const_cast<char * const *>(env));
default_launcher::ignore_unused(::write(pg.p[1], &errno, sizeof(int)));
BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category());
detail::on_exec_error(*this, executable, argv, ec, inits...);
::exit(EXIT_FAILURE);
return basic_process<Executor>{exec};
}
ctx.notify_fork(net::execution_context::fork_parent);
::close(pg.p[1]);
pg.p[1] = -1;
::close(pg_wait.p[1]);
pg_wait.p[1] = -1;
int child_error{0};
int count = -1;
while ((count = ::read(pg.p[0], &child_error, sizeof(child_error))) == -1)
{
int err = errno;
if ((err != EAGAIN) && (err != EINTR))
{
BOOST_PROCESS_V2_ASSIGN_EC(ec, err, system_category());
break;
}
}
if (count != 0)
BOOST_PROCESS_V2_ASSIGN_EC(ec, child_error, system_category());
if (ec)
{
detail::on_error(*this, executable, argv, ec, inits...);
return basic_process<Executor>{exec};
}
std::swap(fd, pg_wait.p[0]);
}
basic_process<Executor> proc(exec, pid, fd);
detail::on_success(*this, executable, argv, ec, inits...);
return proc;
}
};
}
BOOST_PROCESS_V2_END_NAMESPACE
#endif //BOOST_PROCESS_V2_POSIX_PIPE_FORK_LAUNCHER_HPP

View File

@@ -121,6 +121,7 @@ struct vfork_launcher : default_launcher
if (ec)
{
detail::on_error(*this, executable, argv, ec, inits...);
do { ::waitpid(pid, nullptr, 0); } while (errno == EINTR);
return basic_process<Executor>{exec};
}

View File

@@ -231,7 +231,7 @@ struct basic_process
void resume()
{
error_code ec;
suspend(ec);
resume(ec);
if (ec)
detail::throw_error(ec, "resume");
}

View File

@@ -13,7 +13,7 @@
#if defined(BOOST_PROCESS_V2_PIDFD_OPEN)
#include <boost/process/v2/detail/process_handle_fd.hpp>
#elif defined(BOOST_PROCESS_V2_PDFORK)
#elif defined(BOOST_PROCESS_V2_PDFORK) || defined(BOOST_PROCESS_V2_PIPEFORK)
#include <boost/process/v2/detail/process_handle_fd_or_signal.hpp>
#else
// with asio support we could use EVFILT_PROC:NOTE_EXIT as well.
@@ -26,7 +26,7 @@ BOOST_PROCESS_V2_BEGIN_NAMESPACE
#if defined(GENERATING_DOCUMENTATION)
/** A process handle is an unmanaged version of a process.
* This means it does not terminate the proces on destruction and
* This means it does not terminate the process on destruction and
* will not keep track of the exit-code.
*
* Note that the exit code might be discovered early, during a call to `running`.
@@ -107,9 +107,9 @@ struct basic_process_handle
void request_exit()
/// Unconditionally terminates the process and stores the exit code in exit_status.
void terminate(native_exit_code_type &exit_status, error_code &ec);\
void terminate(native_exit_code_type &exit_status, error_code &ec);
/// Throwing @overload void terminate(native_exit_code_type &exit_code, error_code & ec)
void terminate(native_exit_code_type &exit_status);/
void terminate(native_exit_code_type &exit_status);
/// Checks if the current process is running.
/**If it has already completed, it assigns the exit code to `exit_code`.
@@ -137,7 +137,7 @@ using basic_process_handle = detail::basic_process_handle_win<Executor>;
#if defined(BOOST_PROCESS_V2_PIDFD_OPEN)
template<typename Executor = net::any_io_executor>
using basic_process_handle = detail::basic_process_handle_fd<Executor>;
#elif defined(BOOST_PROCESS_V2_PDFORK) || defined(BOOST_PROCESS_V2_PIPE_LAUNCHER)
#elif defined(BOOST_PROCESS_V2_PDFORK) || defined(BOOST_PROCESS_V2_PIPEFORK)
template<typename Executor = net::any_io_executor>
using basic_process_handle = detail::basic_process_handle_fd_or_signal<Executor>;
#else

View File

@@ -31,8 +31,33 @@
#endif
BOOST_PROCESS_V2_BEGIN_NAMESPACE
template<typename T>
struct is_readable_pipe : std::false_type
{
};
template<typename Executor>
struct is_readable_pipe<asio::basic_readable_pipe<Executor>> : std::true_type
{
};
template<typename T>
struct is_writable_pipe : std::false_type
{
};
template<typename Executor>
struct is_writable_pipe<asio::basic_writable_pipe<Executor>> : std::true_type
{
};
namespace detail
{
#if defined(BOOST_PROCESS_V2_WINDOWS)
struct handle_closer
@@ -104,16 +129,10 @@ struct process_io_binding
}
template<typename Executor>
process_io_binding(net::basic_readable_pipe<Executor> & pipe)
template<typename ReadablePipe>
process_io_binding(ReadablePipe & readable_pipe,
typename std::enable_if<is_readable_pipe<ReadablePipe>::value && Target != STDIN_FILENO>::type * = nullptr)
{
if (Target == STD_INPUT_HANDLE)
{
auto h_ = pipe.native_handle();
h = std::unique_ptr<void, handle_closer>{h_, get_flags(h_)};
return ;
}
net::detail::native_pipe_handle p[2];
error_code ec;
net::detail::create_pipe(p, ec);
@@ -125,15 +144,10 @@ struct process_io_binding
}
template<typename Executor>
process_io_binding(net::basic_writable_pipe<Executor> & pipe)
template<typename WritablePipe>
process_io_binding(WritablePipe & writable_pipe,
typename std::enable_if<is_writable_pipe<WritablePipe>::value && Target == STDIN_FILENO>::type * = nullptr)
{
if (Target != STD_INPUT_HANDLE)
{
auto h_ = pipe.native_handle();
h = std::unique_ptr<void, handle_closer>{h_, get_flags(h_)};
return ;
}
net::detail::native_pipe_handle p[2];
error_code ec;
net::detail::create_pipe(p, ec);
@@ -166,6 +180,31 @@ struct process_io_binding
}
process_io_binding() = default;
process_io_binding(const process_io_binding &) = delete;
process_io_binding & operator=(const process_io_binding &) = delete;
process_io_binding(process_io_binding && other) noexcept
: fd(other.fd), fd_needs_closing(other.fd), ec(other.ec)
{
other.fd = target;
other.fd_needs_closing = false;
other.ec = {};
}
process_io_binding & operator=(process_io_binding && other) noexcept
{
if (fd_needs_closing)
::close(fd);
fd = other.fd;
fd_needs_closing = other.fd_needs_closing;
ec = other.ec;
other.fd = target;
other.fd_needs_closing = false;
other.ec = {};
return *this;
}
template<typename Stream>
process_io_binding(Stream && str, decltype(std::declval<Stream>().native_handle()) * = nullptr)
@@ -182,15 +221,10 @@ struct process_io_binding
{
}
template<typename Executor>
process_io_binding(net::basic_readable_pipe<Executor> & readable_pipe)
template<typename ReadablePipe>
process_io_binding(ReadablePipe & readable_pipe,
typename std::enable_if<is_readable_pipe<ReadablePipe>::value && Target != STDIN_FILENO>::type * = nullptr)
{
if (Target == STDIN_FILENO)
{
fd = readable_pipe.native_handle();
return ;
}
net::detail::native_pipe_handle p[2];
net::detail::create_pipe(p, ec);
if (ec)
@@ -207,15 +241,10 @@ struct process_io_binding
}
template<typename Executor>
process_io_binding(net::basic_writable_pipe<Executor> & writable_pipe)
template<typename WritablePipe>
process_io_binding(WritablePipe & writable_pipe,
typename std::enable_if<is_writable_pipe<WritablePipe>::value && Target == STDIN_FILENO>::type * = nullptr)
{
if (Target != STDIN_FILENO)
{
fd = writable_pipe.native_handle();
return ;
}
net::detail::native_pipe_handle p[2];
error_code ec;
net::detail::create_pipe(p, ec);

View File

@@ -97,7 +97,7 @@ inline void invoke_on_error(Launcher & /*launcher*/, const filesystem::path &/*e
template<typename Launcher, typename Init>
inline auto invoke_on_error(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
const error_code & ec, Init && init, derived && )
-> decltype(init.on_error(launcher, ec, executable, cmd_line, ec))
-> decltype(init.on_error(launcher, executable, cmd_line, ec))
{
init.on_error(launcher, executable, cmd_line, ec);
}
@@ -109,7 +109,7 @@ inline std::false_type probe_on_error(
template<typename Launcher, typename Init>
inline auto probe_on_error(Launcher & launcher, Init && init, derived && )
-> std::is_same<error_code, decltype(init.on_error(launcher, std::declval<const filesystem::path &>(), std::declval<std::wstring &>(), std::declval<std::error_code&>()))>;
-> std::is_same<error_code, decltype(init.on_error(launcher, std::declval<const filesystem::path &>(), std::declval<std::wstring &>(), std::declval<error_code&>()))>;
template<typename Launcher, typename Init>
using has_on_error = decltype(probe_on_error(std::declval<Launcher&>(), std::declval<Init>(), derived{}));

View File

@@ -10,7 +10,7 @@
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; url=../../doc/html/process.html">
<meta http-equiv="refresh" content="0; url=doc/html/index.html">
<title>Boost.Process</title>
<style>
body {
@@ -26,7 +26,7 @@
<body>
<p>
Automatic redirection failed, please go to
<a href="../../doc/html/process.html">../../doc/html/process.html</a>
<a href="doc/html/index.html">doc/html/index.html</a>
</p>
<p>
&copy; 2016 Klemens D. Morgenstern

View File

@@ -51,7 +51,7 @@ void unset(basic_cstring_ref<char_type, key_char_traits<char_type>> key, error_c
}
native_handle_type load_native_handle() { return ::environ; }
native_handle_type load_native_handle() { return environ; }
native_iterator next(native_iterator nh)

View File

@@ -210,10 +210,8 @@ std::size_t size_as_wide(const char * in, std::size_t size, error_code &)
const auto from = in;
const auto from_end = from + size;
const char * from_next = from;
std::size_t char_count = 0u;
while (from_next < from_end)
{
++char_count;
unsigned int octet_count = get_octet_count(*from_next);
// The buffer may represent incomplete characters, so terminate early if one is found
if (octet_count > static_cast<std::size_t>(from_end - from_next))

View File

@@ -100,7 +100,7 @@ struct exit_code_category final : public error_category
# if defined(SIGILL)
case SIGILL: return "SIGILL: Illegal Instruction";
# endif
# if defined(SIGINFO)
# if defined(SIGINFO) && SIGINFO != SIGPWR
case SIGINFO: return "SIGINFO: A synonym for SIGPWR";
# endif
# if defined(SIGINT)

View File

@@ -124,7 +124,7 @@ filesystem::path cwd(boost::process::v2::pid_type pid, error_code & ec)
filesystem::path("/proc") / std::to_string(pid) / "cwd", ec
);
#elif defined(__sun)
return fileystem::canonical(
return filesystem::canonical(
filesystem::path("/proc") / std::to_string(pid) / "path/cwd", ec
);
#endif

View File

@@ -141,7 +141,7 @@ filesystem::path exe(boost::process::v2::pid_type pid, error_code & ec)
filesystem::path("/proc") / std::to_string(pid) / "exe", ec
);
#elif defined(__sun)
return fileystem::canonical(
return filesystem::canonical(
filesystem::path("/proc") / std::to_string(pid) / "path/a.out", ec
);
#endif

View File

@@ -178,6 +178,8 @@ pid_type parent_pid(pid_type pid, error_code & ec)
std::vector<pid_type> child_pids(pid_type pid, error_code & ec)
{
std::vector<pid_type> vec;
#if defined(PROC_PPID_ONLY)
vec.resize(proc_listpids(PROC_PPID_ONLY, (uint32_t)pid, nullptr, 0) / sizeof(pid_type));
const auto sz = proc_listpids(PROC_PPID_ONLY, (uint32_t)pid, &vec[0], sizeof(pid_type) * vec.size());
if (sz < 0)
@@ -186,6 +188,9 @@ std::vector<pid_type> child_pids(pid_type pid, error_code & ec)
return {};
}
vec.resize(sz);
#else
BOOST_PROCESS_V2_ASSIGN_EC(ec, ENOTSUP, system_category());
#endif
return vec;
}

View File

@@ -185,7 +185,7 @@ void close_all(const std::vector<int> & whitelist, error_code & ec)
return ;
}
auto dir_fd = ::dirfd(dir.get());
auto dir_fd = dirfd(dir.get());
if (dir_fd == -1)
{
ec = BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error();

View File

@@ -21,9 +21,7 @@
#include <boost/algorithm/string/predicate.hpp>
namespace bp = boost::process;
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(args, *boost::unit_test::timeout(2))
{

View File

@@ -19,7 +19,7 @@
#include <boost/process/v1/error.hpp>
#include <boost/process/v1/child.hpp>
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(implicit_args_fs_path)

View File

@@ -3,11 +3,34 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_ASIO_NO_DEPRECATED 1
#include <boost/process.hpp>
#include <boost/process/v1/args.hpp>
#include <boost/process/v1/async.hpp>
#include <boost/process/v1/async_pipe.hpp>
#include <boost/process/v1/async_system.hpp>
#include <boost/process/v1/child.hpp>
#include <boost/process/v1/cmd.hpp>
#include <boost/process/v1/env.hpp>
#include <boost/process/v1/environment.hpp>
#include <boost/process/v1/error.hpp>
#include <boost/process/v1/exception.hpp>
#include <boost/process/v1/exe.hpp>
#include <boost/process/v1/extend.hpp>
#include <boost/process/v1/filesystem.hpp>
#include <boost/process/v1/group.hpp>
#include <boost/process/v1/handles.hpp>
#include <boost/process/v1/io.hpp>
#include <boost/process/v1/locale.hpp>
#include <boost/process/v1/pipe.hpp>
#include <boost/process/v1/search_path.hpp>
#include <boost/process/v1/shell.hpp>
#include <boost/process/v1/spawn.hpp>
#include <boost/process/v1/start_dir.hpp>
#include <boost/process/v1/system.hpp>
int main() {}
#if defined(BOOST_POSIX_API)
#include <boost/process/v1/posix.hpp>
#else
#include <boost/process/v1/windows.hpp>
#endif
#endif

View File

@@ -25,7 +25,7 @@
using namespace std;
namespace bp = boost::process;
namespace bp = boost::process::v1;
#if __APPLE__
auto abort_sig = signal(SIGALRM, +[](int){std::terminate();});

View File

@@ -29,7 +29,7 @@ BOOST_AUTO_TEST_SUITE( async );
using namespace std;
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(async_out_future, *boost::unit_test::timeout(2))
{
@@ -103,4 +103,4 @@ BOOST_AUTO_TEST_CASE(emtpy_out, *boost::unit_test::timeout(2))
BOOST_CHECK_EQUAL(fut.get(), "");
}
BOOST_AUTO_TEST_SUITE_END();
BOOST_AUTO_TEST_SUITE_END();

View File

@@ -20,7 +20,7 @@
#include <boost/asio/streambuf.hpp>
using namespace std;
namespace bp = boost::process;
namespace bp = boost::process::v1;
namespace asio = boost::asio;
BOOST_AUTO_TEST_SUITE( async );

View File

@@ -18,7 +18,7 @@
#include <boost/process/v1/async_system.hpp>
#include <system_error>
namespace bp = boost::process;;
namespace bp = boost::process::v1;
void fail_func()
{

View File

@@ -23,7 +23,7 @@
#include <vector>
#include <array>
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_SUITE( async );
BOOST_AUTO_TEST_CASE(future, *boost::unit_test::timeout(15))

View File

@@ -27,7 +27,7 @@
#include <array>
BOOST_AUTO_TEST_SUITE( async );
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(stackful, *boost::unit_test::timeout(15))
{
using boost::unit_test::framework::master_test_suite;

View File

@@ -26,7 +26,7 @@
#include <array>
BOOST_AUTO_TEST_SUITE( async );
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(stackful, *boost::unit_test::timeout(15))
{
using boost::unit_test::framework::master_test_suite;

View File

@@ -26,7 +26,7 @@
#include <array>
BOOST_AUTO_TEST_SUITE( async );
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(stackful_except, *boost::unit_test::timeout(15))
{
using boost::unit_test::framework::master_test_suite;

View File

@@ -25,7 +25,7 @@
#include <array>
BOOST_AUTO_TEST_SUITE( async );
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(stackless, *boost::unit_test::timeout(15))
{
using boost::unit_test::framework::master_test_suite;

View File

@@ -39,7 +39,7 @@ typedef boost::asio::posix::stream_descriptor pipe_end;
#endif
namespace fs = boost::process::v1::filesystem;
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_SUITE( bind_stderr );
BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(2))

View File

@@ -43,7 +43,7 @@ typedef boost::asio::posix::stream_descriptor pipe_end;
namespace fs = boost::process::v1::filesystem;
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(10))
{

View File

@@ -22,7 +22,7 @@
#include <string>
#include <iostream>
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_SUITE( bind_stdin_stdout );
BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(10))

View File

@@ -42,7 +42,7 @@ BOOST_AUTO_TEST_SUITE( bind_stdout );
namespace fs = boost::process::v1::filesystem;
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(5))
{

View File

@@ -34,7 +34,7 @@ typedef boost::asio::windows::stream_handle pipe_end;
typedef boost::asio::posix::stream_descriptor pipe_end;
#endif
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_SUITE( bind_stdout_stderr );

View File

@@ -22,7 +22,7 @@
# include <sys/wait.h>
#endif
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(close_stderr)

View File

@@ -22,7 +22,7 @@
# include <sys/wait.h>
#endif
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(close_stdin)
{

View File

@@ -22,7 +22,7 @@
# include <sys/wait.h>
#endif
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(close_stdout)
{

View File

@@ -26,7 +26,7 @@
#include <boost/system/error_code.hpp>
#include <cstdlib>
namespace bp = boost::process;
namespace bp = boost::process::v1;
namespace fs = boost::process::v1::filesystem;

View File

@@ -27,7 +27,7 @@
#include <stdlib.h>
#include <list>
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(inherit_env, *boost::unit_test::timeout(2))
{

View File

@@ -12,7 +12,7 @@
#include <boost/test/included/unit_test.hpp>
#include <boost/process/v1/environment.hpp>
namespace bp = boost::process;
namespace bp = boost::process::v1;
namespace std

View File

@@ -19,7 +19,7 @@
namespace bp = boost::process;
namespace bp = boost::process::v1;
struct err_set
{

View File

@@ -26,7 +26,7 @@ typedef boost::asio::windows::stream_handle pipe_end;
typedef boost::asio::posix::stream_descriptor pipe_end;
#endif
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(sync_wait, *boost::unit_test::timeout(10))
{

View File

@@ -17,7 +17,7 @@
#include <boost/process/v1/extend.hpp>
namespace bp = boost::process;
namespace bp = boost::process::v1;
struct run_exe

View File

@@ -29,7 +29,7 @@
#include <iostream>
#include <cstdlib>
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(group_test, *boost::unit_test::timeout(5))
{

View File

@@ -30,7 +30,7 @@
#include <iostream>
#include <cstdlib>
namespace bp = boost::process;
namespace bp = boost::process::v1;

View File

@@ -7,9 +7,7 @@
#define BOOST_TEST_IGNORE_SIGCHLD
#include <boost/test/included/unit_test.hpp>
#include <iostream>
#include <boost/process.hpp>
#include <boost/process/v1/system.hpp>
#include <boost/process/v1/handles.hpp>
#include <boost/process/v1/pipe.hpp>
#include <boost/process/v1/io.hpp>
@@ -32,8 +30,7 @@
#include <dirent.h>
#endif
namespace fs = boost::process::v1::filesystem;
namespace bp = boost::process;
namespace bp = boost::process::v1;
namespace bt = boost::this_process;
BOOST_AUTO_TEST_CASE(leak_test, *boost::unit_test::timeout(5))
@@ -110,7 +107,7 @@ BOOST_AUTO_TEST_CASE(leak_test, *boost::unit_test::timeout(5))
BOOST_CHECK(!bt::is_stream_handle(event_fd , ec)); BOOST_CHECK_MESSAGE(!ec, ec.message());
#endif
auto od = ::opendir(".");
int dir_fd = ::dirfd(od);
int dir_fd = dirfd(od);
BOOST_CHECK(!bt::is_stream_handle(dir_fd , ec)); BOOST_CHECK_MESSAGE(!ec, ec.message());
#endif

View File

@@ -4,4 +4,32 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/process.hpp>
#include <boost/process/v1/args.hpp>
#include <boost/process/v1/async.hpp>
#include <boost/process/v1/async_pipe.hpp>
#include <boost/process/v1/async_system.hpp>
#include <boost/process/v1/child.hpp>
#include <boost/process/v1/cmd.hpp>
#include <boost/process/v1/env.hpp>
#include <boost/process/v1/environment.hpp>
#include <boost/process/v1/error.hpp>
#include <boost/process/v1/exception.hpp>
#include <boost/process/v1/exe.hpp>
#include <boost/process/v1/extend.hpp>
#include <boost/process/v1/filesystem.hpp>
#include <boost/process/v1/group.hpp>
#include <boost/process/v1/handles.hpp>
#include <boost/process/v1/io.hpp>
#include <boost/process/v1/locale.hpp>
#include <boost/process/v1/pipe.hpp>
#include <boost/process/v1/search_path.hpp>
#include <boost/process/v1/shell.hpp>
#include <boost/process/v1/spawn.hpp>
#include <boost/process/v1/start_dir.hpp>
#include <boost/process/v1/system.hpp>
#if defined(BOOST_POSIX_API)
#include <boost/process/v1/posix.hpp>
#else
#include <boost/process/v1/windows.hpp>
#endif

View File

@@ -3,4 +3,32 @@
// 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)
#include <boost/process.hpp>
#include <boost/process/v1/args.hpp>
#include <boost/process/v1/async.hpp>
#include <boost/process/v1/async_pipe.hpp>
#include <boost/process/v1/async_system.hpp>
#include <boost/process/v1/child.hpp>
#include <boost/process/v1/cmd.hpp>
#include <boost/process/v1/env.hpp>
#include <boost/process/v1/environment.hpp>
#include <boost/process/v1/error.hpp>
#include <boost/process/v1/exception.hpp>
#include <boost/process/v1/exe.hpp>
#include <boost/process/v1/extend.hpp>
#include <boost/process/v1/filesystem.hpp>
#include <boost/process/v1/group.hpp>
#include <boost/process/v1/handles.hpp>
#include <boost/process/v1/io.hpp>
#include <boost/process/v1/locale.hpp>
#include <boost/process/v1/pipe.hpp>
#include <boost/process/v1/search_path.hpp>
#include <boost/process/v1/shell.hpp>
#include <boost/process/v1/spawn.hpp>
#include <boost/process/v1/start_dir.hpp>
#include <boost/process/v1/system.hpp>
#if defined(BOOST_POSIX_API)
#include <boost/process/v1/posix.hpp>
#else
#include <boost/process/v1/windows.hpp>
#endif

View File

@@ -6,5 +6,30 @@
#include <boost/system/api_config.hpp>
#if defined(BOOST_WINDOWS_API)
#define BOOST_NO_ANSI_APIS 1
#include <boost/process/v1/args.hpp>
#include <boost/process/v1/async.hpp>
#include <boost/process/v1/async_pipe.hpp>
#include <boost/process/v1/async_system.hpp>
#include <boost/process/v1/child.hpp>
#include <boost/process/v1/cmd.hpp>
#include <boost/process/v1/env.hpp>
#include <boost/process/v1/environment.hpp>
#include <boost/process/v1/error.hpp>
#include <boost/process/v1/exception.hpp>
#include <boost/process/v1/exe.hpp>
#include <boost/process/v1/extend.hpp>
#include <boost/process/v1/filesystem.hpp>
#include <boost/process/v1/group.hpp>
#include <boost/process/v1/handles.hpp>
#include <boost/process/v1/io.hpp>
#include <boost/process/v1/locale.hpp>
#include <boost/process/v1/pipe.hpp>
#include <boost/process/v1/search_path.hpp>
#include <boost/process/v1/shell.hpp>
#include <boost/process/v1/spawn.hpp>
#include <boost/process/v1/start_dir.hpp>
#include <boost/process/v1/system.hpp>
#include <boost/process/v1/windows.hpp>
#endif
#include <boost/process.hpp>
int main() {}

View File

@@ -10,7 +10,8 @@
#define BOOST_TEST_MAIN
#define BOOST_TEST_IGNORE_SIGCHLD
#include <boost/test/included/unit_test.hpp>
#include <boost/process.hpp>
#include <boost/process/v1/async.hpp>
#include <boost/process/v1/child.hpp>
#include <boost/asio.hpp>
#include <chrono>
#include <thread>
@@ -26,7 +27,7 @@ BOOST_AUTO_TEST_CASE(single_ios, *boost::unit_test::timeout(6))
return;
}
namespace bp = boost::process;
namespace bp = boost::process::v1;
boost::asio::io_context ios;
std::chrono::steady_clock::time_point p1, p2;

View File

@@ -10,7 +10,8 @@
#define BOOST_TEST_MAIN
#define BOOST_TEST_IGNORE_SIGCHLD
#include <boost/test/included/unit_test.hpp>
#include <boost/process.hpp>
#include <boost/process/v1/async.hpp>
#include <boost/process/v1/child.hpp>
#include <boost/asio.hpp>
#include <chrono>
#include <thread>
@@ -26,7 +27,7 @@ BOOST_AUTO_TEST_CASE(double_ios, *boost::unit_test::timeout(6))
return;
}
namespace bp = boost::process;
namespace bp = boost::process::v1;
boost::asio::io_context ios;
std::chrono::steady_clock::time_point p1, p2;

View File

@@ -10,7 +10,8 @@
#define BOOST_TEST_MAIN
#define BOOST_TEST_IGNORE_SIGCHLD
#include <boost/test/included/unit_test.hpp>
#include <boost/process.hpp>
#include <boost/process/v1/async.hpp>
#include <boost/process/v1/child.hpp>
#include <boost/asio.hpp>
#include <chrono>
#include <thread>
@@ -26,7 +27,7 @@ BOOST_AUTO_TEST_CASE(double_ios_threaded, *boost::unit_test::timeout(6))
return;
}
namespace bp = boost::process;
namespace bp = boost::process::v1;
boost::asio::io_context ios;
std::chrono::steady_clock::time_point p1, p2;

View File

@@ -14,7 +14,7 @@
#include <boost/process/v1/environment.hpp>
using namespace std;
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_SUITE( pipe_tests );

View File

@@ -29,7 +29,7 @@
BOOST_AUTO_TEST_SUITE( pipe_tests );
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(5))
{

View File

@@ -11,10 +11,14 @@
#define BOOST_TEST_IGNORE_SIGCHLD
#include <boost/test/included/unit_test.hpp>
#include <boost/process.hpp>
#include <boost/process/v1/posix.hpp>
#include <boost/process/v1/child.hpp>
#include <boost/process/v1/environment.hpp>
#include <boost/process/v1/filesystem.hpp>
#include <boost/process/v1/io.hpp>
#include <boost/process/v1/pipe.hpp>
#include <boost/process/v1/posix.hpp>
#include <boost/process/v1/spawn.hpp>
#include <boost/process/v1/system.hpp>
#if !defined(BOOST_PROCESS_USE_STD_FS)
#include <boost/filesystem/directory.hpp>
@@ -29,7 +33,7 @@
#include <errno.h>
namespace fs = boost::process::v1::filesystem;
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(bind_fd, *boost::unit_test::timeout(2))
{

View File

@@ -15,7 +15,7 @@
#include <boost/process/v1/error.hpp>
#include <boost/process/v1/child.hpp>
namespace bp = boost::process;
namespace bp = boost::process::v1;
int main(int argc, char* argv[])
{

View File

@@ -18,7 +18,7 @@
#include <boost/process/v1/error.hpp>
#include <boost/process/v1/child.hpp>
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(run_exe_success)

View File

@@ -13,7 +13,7 @@
#include <boost/process/v1/filesystem.hpp>
#include <string>
namespace bp = boost::process;
namespace bp = boost::process::v1;
namespace fs = boost::process::v1::filesystem;
BOOST_AUTO_TEST_CASE(search_path)

View File

@@ -22,7 +22,7 @@
#include <boost/process/v1/child.hpp>
#include <boost/process/v1/shell.hpp>
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(shell_simple, *boost::unit_test::timeout(5))

View File

@@ -13,7 +13,7 @@
#include <boost/process/v1/filesystem.hpp>
#include <system_error>
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(shell_set_on_error)
{

View File

@@ -39,7 +39,7 @@ typedef boost::asio::posix::stream_descriptor pipe_end;
#endif
namespace fs = boost::process::v1::filesystem;
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(sync_spawn, *boost::unit_test::timeout(5))
{

View File

@@ -35,7 +35,7 @@ typedef boost::asio::posix::stream_descriptor pipe_end;
#endif
namespace fs = boost::process::v1::filesystem;
namespace bp = boost::process;
namespace bp = boost::process::v1;
int main()
{

View File

@@ -10,14 +10,19 @@
#define BOOST_TEST_MAIN
#define BOOST_TEST_IGNORE_SIGCHLD
#include <boost/test/included/unit_test.hpp>
#include <boost/process.hpp>
#include <boost/system/error_code.hpp>
#include <boost/process/v1/args.hpp>
#include <boost/process/v1/child.hpp>
#include <boost/process/v1/exe.hpp>
#include <boost/process/v1/filesystem.hpp>
#include <boost/process/v1/io.hpp>
#include <boost/process/v1/pipe.hpp>
#include <boost/process/v1/start_dir.hpp>
#include <boost/algorithm/string/compare.hpp>
#include <string>
#include <iostream>
namespace bp = boost::process;
#include <string>
namespace bp = boost::process::v1;
struct test_dir

View File

@@ -2,7 +2,9 @@
// 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)
#include <boost/process.hpp>
#include <boost/process/v1/child.hpp>
#include <boost/process/v1/io.hpp>
#include <boost/process/v1/group.hpp>
#include <boost/program_options.hpp>
#include <vector>
@@ -20,7 +22,7 @@ int main(int argc, char *argv[])
{
using namespace std;
using namespace boost::program_options;
using namespace boost::process;
using namespace boost::process::v1;
bool launch_detached = false;
bool launch_attached = false;

View File

@@ -44,7 +44,7 @@ typedef boost::asio::posix::stream_descriptor pipe_end;
#endif
namespace fs = boost::process::v1::filesystem;
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(system_exit_code, *boost::unit_test::timeout(5))
{

View File

@@ -38,7 +38,7 @@
#include <cstdlib>
namespace fs = boost::process::v1::filesystem;
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(explicit_async_io, *boost::unit_test::timeout(2))
{

View File

@@ -20,7 +20,7 @@
#include <system_error>
#include <thread>
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(terminate_set_on_error, *boost::unit_test::timeout(5))
{

View File

@@ -9,11 +9,11 @@
#include <boost/core/lightweight_test.hpp>
#include <boost/process.hpp>
#include <boost/process/v1/child.hpp>
#include <boost/process/v1/cmd.hpp>
#include <system_error>
namespace bp = boost::process;
namespace bp = boost::process::v1;
int main(int argc, char* argv[])
{

View File

@@ -11,7 +11,7 @@
#define BOOST_TEST_IGNORE_SIGCHLD
#include <boost/test/included/unit_test.hpp>
#include <boost/process.hpp>
#include <boost/process/v1.hpp>
#include <boost/process/v1/posix.hpp>
#include <system_error>
@@ -21,7 +21,7 @@
#include <sys/wait.h>
#include <errno.h>
namespace bp = boost::process;
namespace bp = boost::process::v1;
#if defined(BOOST_POSIX_HAS_VFORK)

View File

@@ -22,7 +22,7 @@
# include <signal.h>
#endif
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_SUITE( wait_test );

View File

@@ -21,7 +21,7 @@
# include <signal.h>
#endif
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_SUITE( wait_test);
BOOST_AUTO_TEST_CASE(wait_for)

View File

@@ -21,7 +21,7 @@
#include <boost/algorithm/string/predicate.hpp>
namespace bp = boost::process;
namespace bp = boost::process::v1;
BOOST_AUTO_TEST_CASE(wargs, *boost::unit_test::timeout(2))

Some files were not shown because too many files have changed in this diff Show More