mirror of
https://github.com/boostorg/process.git
synced 2026-01-20 16:52:14 +00:00
Compare commits
50 Commits
boost-1.82
...
cmd-empty-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
743f0cca35 | ||
|
|
81ad643b00 | ||
|
|
6fd1200ab7 | ||
|
|
c7bdccd57e | ||
|
|
d6bcb0014a | ||
|
|
e5f0f245bd | ||
|
|
a4a3770501 | ||
|
|
1e5892b8fb | ||
|
|
85b29d6442 | ||
|
|
b9ee759365 | ||
|
|
f3b163a933 | ||
|
|
be2ae2c3cf | ||
|
|
b2f5ebc760 | ||
|
|
e34557faa0 | ||
|
|
a9f083f45c | ||
|
|
b5ab94c932 | ||
|
|
9ceda79fa2 | ||
|
|
68cbeae491 | ||
|
|
ae778f36a8 | ||
|
|
0671e4a133 | ||
|
|
cbf944c57b | ||
|
|
5f2b8c53f4 | ||
|
|
dac3614a38 | ||
|
|
2fc71ca0a3 | ||
|
|
404682d75d | ||
|
|
9fbbdc3421 | ||
|
|
3df0009a2f | ||
|
|
ecb384b253 | ||
|
|
05bce942c1 | ||
|
|
dcf5d8ce41 | ||
|
|
4209f8ee6e | ||
|
|
d9513269cc | ||
|
|
293f28dab6 | ||
|
|
fe1b629b5d | ||
|
|
278fa57214 | ||
|
|
1addfba12e | ||
|
|
4cc469b2a4 | ||
|
|
6e4d1e29d2 | ||
|
|
dada865fd0 | ||
|
|
380dd1b00f | ||
|
|
7832cb6af3 | ||
|
|
68f4c50be9 | ||
|
|
cd226a7616 | ||
|
|
4243ce72f8 | ||
|
|
9065833e61 | ||
|
|
7cb7af6c8b | ||
|
|
90cbe7cec0 | ||
|
|
df33c1ad7b | ||
|
|
bbabea30dd | ||
|
|
8a61f8daa3 |
@@ -19,7 +19,7 @@ def main(ctx):
|
||||
linux_cxx("docs", "", packages="docbook docbook-xml docbook-xsl xsltproc libsaxonhe-java default-jre-headless flex libfl-dev bison unzip rsync", image="cppalliance/droneubuntu1804:1", buildtype="docs", buildscript="drone", environment={"COMMENT": "docs"}, globalenv=globalenv),
|
||||
linux_cxx("asan", "g++-8", packages="g++-8", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'COMMENT': 'asan', 'B2_VARIANT': 'debug', 'B2_TOOLSET': 'gcc-8', 'B2_CXXSTD': '11', 'B2_ASAN': '1', 'B2_DEFINES': 'BOOST_NO_STRESS_TEST=1', 'DRONE_EXTRA_PRIVILEGED': 'True', 'DRONE_JOB_UUID': '356a192b79'}, globalenv=globalenv, privileged=True),
|
||||
linux_cxx("ubsan", "g++-8", packages="g++-8", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'COMMENT': 'ubsan', 'B2_VARIANT': 'debug', 'B2_TOOLSET': 'gcc-8', 'B2_CXXSTD': '11', 'B2_UBSAN': '1', 'B2_DEFINES': 'BOOST_NO_STRESS_TEST=1', 'B2_LINKFLAGS': '-fuse-ld=gold', 'DRONE_JOB_UUID': '77de68daec'}, globalenv=globalenv),
|
||||
#linux_cxx("gcc 11 arm64", "g++-11", packages="g++-11", buildtype="boost", buildscript="drone", image="cppalliance/droneubuntu2004:multiarch", environment={ 'B2_TOOLSET': 'gcc-11', 'B2_CXXSTD': '11', 'DRONE_JOB_UUID': '17ba079169m'}, arch="arm64", globalenv=globalenv),
|
||||
linux_cxx("gcc 11 arm64", "g++-11", packages="g++-11", buildtype="boost", buildscript="drone", image="cppalliance/droneubuntu2004:multiarch", environment={ 'B2_TOOLSET': 'gcc-11', 'B2_CXXSTD': '11', 'DRONE_JOB_UUID': '17ba079169m'}, arch="arm64", globalenv=globalenv),
|
||||
linux_cxx("GCC 10, Debug + Coverage", "g++-10", packages="g++-10 libssl-dev libffi-dev binutils-gold gdb",
|
||||
image="cppalliance/droneubuntu2004:1", buildtype="boost", buildscript="drone", environment={"GCOV": "gcov-10", "LCOV_VERSION": "1.15", "VARIANT": "process_coverage", "TOOLSET": "gcc", "COMPILER": "g++-10", "CXXSTD": "11", "DRONE_BEFORE_INSTALL" : "process_coverage", "CODECOV_TOKEN": {"from_secret": "codecov_token"}}, globalenv=globalenv, privileged=True),
|
||||
# A set of jobs based on the earlier .travis.yml configuration:
|
||||
|
||||
125
.github/workflows/ci.yml
vendored
125
.github/workflows/ci.yml
vendored
@@ -17,6 +17,10 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- toolset: gcc-4.8
|
||||
cxxstd: "11"
|
||||
os: ubuntu-18.04
|
||||
install: g++-4.8
|
||||
- toolset: gcc-5
|
||||
cxxstd: "11,14,1z"
|
||||
os: ubuntu-18.04
|
||||
@@ -28,10 +32,21 @@ jobs:
|
||||
- toolset: gcc-7
|
||||
cxxstd: "11,14,17"
|
||||
os: ubuntu-18.04
|
||||
- toolset: gcc-8
|
||||
cxxstd: "11,14,17,2a"
|
||||
os: ubuntu-18.04
|
||||
install: g++-8
|
||||
- toolset: gcc-9
|
||||
cxxstd: "11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
- toolset: gcc-10
|
||||
cxxstd: "11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
install: g++-10
|
||||
- toolset: gcc-11
|
||||
cxxstd: "11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
install: g++-11
|
||||
- toolset: gcc-12
|
||||
cxxstd: "11,14,17,20,2b"
|
||||
os: ubuntu-22.04
|
||||
@@ -247,4 +262,114 @@ jobs:
|
||||
cmake --build .
|
||||
ctest --output-on-failure --no-tests=error
|
||||
|
||||
posix-cmake-install:
|
||||
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: Configure
|
||||
run: |
|
||||
cd ../boost-root
|
||||
mkdir __build__ && cd __build__
|
||||
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local ..
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
cmake --build . --target install
|
||||
|
||||
- name: Use the installed library
|
||||
run: |
|
||||
cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__
|
||||
cmake -DCMAKE_INSTALL_PREFIX=~/.local ..
|
||||
cmake --build .
|
||||
ctest --output-on-failure --no-tests=error
|
||||
|
||||
posix-cmake-test:
|
||||
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: Configure
|
||||
run: |
|
||||
cd ../boost-root
|
||||
mkdir __build__ && cd __build__
|
||||
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON ..
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
cmake --build . --target tests
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd ../boost-root/__build__
|
||||
ctest --output-on-failure --no-tests=error
|
||||
|
||||
@@ -41,7 +41,7 @@ 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],
|
||||
which also have file-like names, but are in a different scope than the actual file system.
|
||||
|
||||
[note The main reason named pipes are part of this library, is because they need to be internally used for asynchronous communication on windows.]
|
||||
[note The main reason named pipes are part of this library, is because they need to be internally used for asynchrounous communication on windows.]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ else if (pid == 0) //child process
|
||||
for (auto & s : seq)
|
||||
s.<methodname alt="boost::process::extend::handler::on_exec_error">on_exec_error</methodname>(*this);
|
||||
|
||||
<emphasis>unspecified();</emphasis>//here the error is sent to the father process internally
|
||||
<emphasis>unspecified();</emphasis>//here the error is send to the father process interally
|
||||
|
||||
<ulink url="http://en.cppreference.com/w/cpp/utility/program/exit">std::exit</ulink>(<ulink url="http://en.cppreference.com/w/c/program/EXIT_status">EXIT_FAILURE</ulink>);
|
||||
return <classname alt="boost::process::child">child</classname>(); //for C++ compliance
|
||||
@@ -39,7 +39,7 @@ else if (pid == 0) //child process
|
||||
|
||||
<classname alt="boost::process::child">child</classname> c(pid, exit_code);
|
||||
|
||||
<emphasis>unspecified();</emphasis>//here, we read the error from the child process
|
||||
<emphasis>unspecified();</emphasis>//here, we read the the error from the child process
|
||||
|
||||
if (<methodname alt="boost::process::extend::posix_executor::error">error</methodname>())
|
||||
for (auto & s : seq)
|
||||
@@ -48,7 +48,7 @@ else
|
||||
for (auto & s : seq)
|
||||
s.<methodname alt="boost::process::extend::handler::on_error">on_success</methodname>(*this);
|
||||
|
||||
//now we check again, because an on_success handler might've errored.
|
||||
//now we check again, because a on_success handler might've errored.
|
||||
if (<methodname alt="boost::process::extend::posix_executor::error">error</methodname>())
|
||||
{
|
||||
for (auto & s : seq)
|
||||
|
||||
@@ -9,7 +9,7 @@ Additionally, environment can be lists separated by `:` or `;`; `environment::va
|
||||
`environment::value_view` can be used to iterate those.
|
||||
|
||||
Beyond that, the requirements on an environment are a low as possible;
|
||||
an environment is either a list of strings or a list of string-pairs. It is however recommended to use the environment types,
|
||||
an environment is either a list of strings or a list of string-pairs. It is however recommented to use the environment types,
|
||||
as to have the right value comparisons.
|
||||
|
||||
To note is the `find_executable` functions, which searches in an environment for an executable.
|
||||
|
||||
@@ -27,7 +27,7 @@ For process v2, the interfaces is simple:
|
||||
extern asio::io_context ctx;
|
||||
process proc(ctx, "./test", {"--help"}, process_io{nullptr, {}, {}}, process_environment(my_env));
|
||||
|
||||
Every initializer addresses one logical component (e.g. stdio) instead of multiple ones accumulating.
|
||||
Every initializer adresses one logical compoent (e.g. stdio) instead of multiple ones accumulating.
|
||||
Furthermore, every process has a path and arguments, instead of a confusing mixture of cmd-style and
|
||||
exe-args that can be randomly spread out.
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ A launcher is invoked through the call operator.
|
||||
```
|
||||
auto l = windows::as_user_launcher((HANDLE)0xDEADBEEF);
|
||||
asio::io_context ctx;
|
||||
boost::system::error_code ec;
|
||||
boost::system::eror_code ec;
|
||||
auto proc = l(ctx, ec, "C:\\User\\boost\\Downloads\\totally_not_a_virus.exe", {});
|
||||
```
|
||||
|
||||
@@ -38,7 +38,7 @@ Alternatively, the `vfork_launcher` can report errors directly back to the paren
|
||||
Thus some calls to the initializers occur after forking from the child process.
|
||||
|
||||
```
|
||||
struct custom_initializer
|
||||
struct custom_initalizer
|
||||
{
|
||||
// functions called from the parent process:
|
||||
|
||||
@@ -47,7 +47,7 @@ Thus some calls to the initializers occur after forking from the child process.
|
||||
template<typename Launcher>
|
||||
error_code on_setup(Launcher & launcher, const filesystem::path &executable, const char * const * (&cmd_line));
|
||||
|
||||
// called for every initializer if an error occurred during setup or process creation
|
||||
// called for every initializer if an error occured during setup or process creation
|
||||
template<typename Launcher>
|
||||
void on_error(Launcher & launcher, const filesystem::path &executable, const char * const * (&cmd_line),
|
||||
const error_code & ec);
|
||||
@@ -56,7 +56,7 @@ Thus some calls to the initializers occur after forking from the child process.
|
||||
template<typename Launcher>
|
||||
void on_success(Launcher & launcher, const filesystem::path &executable, const char * const * (&cmd_line));
|
||||
|
||||
// called for every initializer if an error occurred when forking, in addition to on_error.
|
||||
// called for every initializer if an error occured when forking, in addtion to on_error.
|
||||
template<typename Launcher>
|
||||
void on_fork_error(Launcher & launcher, const filesystem::path &executable, const char * const * (&cmd_line),
|
||||
const error_code & ec);
|
||||
@@ -94,7 +94,7 @@ The launcher will close all non-whitelisted file descriptors after `on_exec_setu
|
||||
|
||||
[section:windows Windows Launchers]
|
||||
|
||||
Windows launchers are pretty straight forward, they will call the following functions on the initializer if present.
|
||||
Windows launchers are pretty streight forward, they will call the following functions on the initializer if present.
|
||||
|
||||
```
|
||||
struct custom_initializer
|
||||
@@ -103,7 +103,7 @@ Windows launchers are pretty straight forward, they will call the following func
|
||||
template<typename Launcher>
|
||||
error_code on_setup(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line);
|
||||
|
||||
// called for every initializer if an error occurred during setup or process creation
|
||||
// called for every initializer if an error occured during setup or process creation
|
||||
template<typename Launcher>
|
||||
void on_error(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
|
||||
const error_code & ec);
|
||||
|
||||
@@ -32,7 +32,7 @@ also returned from `.wait()`.
|
||||
```
|
||||
|
||||
The normal exit-code is what the subprocess returned from `main`;
|
||||
posix will however add additional information about the process.
|
||||
posix will however add addtional information about the process.
|
||||
This is called the `native_exit_code`.
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ The `.running()` function can be used to detect if the process is still active.
|
||||
|
||||
[section:signal Signalling the subprocess]
|
||||
|
||||
The parent process can signal the subprocess demanding certain actions.
|
||||
The parent process can signal the subprocess demaning certain actions.
|
||||
|
||||
`.terminate` will cause the subprocess to exit immediately (`SIGKILL` on posix).
|
||||
This is the only reliable & portable way to end a subprocess.
|
||||
@@ -76,7 +76,7 @@ interpret as a signal to shutdown.
|
||||
|
||||
[section:execute Execute functions]
|
||||
|
||||
Process v2 provides `execute` and `async_execute` functions that can be used for managed executions.
|
||||
Process v2 provides `execute` and `async_execute` functons that can be used for managed executions.
|
||||
|
||||
```
|
||||
assert(execute(process("/bin/ls", {}) == 0));
|
||||
@@ -90,7 +90,7 @@ The async version supports cancellation and will forward cancellation types as f
|
||||
|
||||
```
|
||||
asio::io_context ctx;
|
||||
asio::steady_timer timeout{ctx, std::chrono::seconds(10)};
|
||||
asio::steady_timer timout{ctx, std::chrono::seconds(10)};
|
||||
|
||||
asio::cancellation_signal sig;
|
||||
async_execute(process("/usr/bin/g++", {"hello_world.cpp"}),
|
||||
|
||||
@@ -23,7 +23,7 @@ automatically connected and the other side will get assigned to the child proces
|
||||
proc.wait();
|
||||
```
|
||||
|
||||
readable pipes can be assigned to `out` an `err`, while writable_pipes can be assigned to `in`.
|
||||
readable pipes can be assigned to `out` an `err``, while writable_pipes can be assigned to `in`.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ else
|
||||
for (auto & s : seq)
|
||||
s.<methodname alt="boost::process::extend::handler::on_error">on_success</methodname>(*this);
|
||||
|
||||
//now we check again, because an on_success handler might've errored.
|
||||
//now we check again, because a on_success handler might've errored.
|
||||
if (<methodname alt="boost::process::extend::windows_executor::error">error</methodname>())
|
||||
{
|
||||
for (auto & s : seq)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2022 Klemens Morgenstern
|
||||
// Copyright (c) 2022Klemens Morgernstern
|
||||
//
|
||||
// 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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2022Klemens Morgenstern
|
||||
// Copyright (c) 2022Klemens Morgernstern
|
||||
//
|
||||
// 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)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
/** \file boost/process/async.hpp
|
||||
|
||||
The header which provides the basic asynchronous features.
|
||||
The header which provides the basic asynchrounous features.
|
||||
It provides the on_exit property, which allows callbacks when the process exits.
|
||||
It also implements the necessary traits for passing an boost::asio::io_context,
|
||||
which is needed for asynchronous communication.
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
/**
|
||||
* \file boost/process/async_system.hpp
|
||||
*
|
||||
* Defines the asynchronous version of the system function.
|
||||
* Defines the asynchrounous version of the system function.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_ASYNC_SYSTEM_HPP
|
||||
|
||||
@@ -39,10 +39,10 @@ inline std::string build_cmd_shell(const std::string & exe, std::vector<std::str
|
||||
//the first one is put directly onto the output,
|
||||
//because then I don't have to copy the whole string
|
||||
arg.insert(arg.begin(), '"' );
|
||||
arg += '"'; //that is the post one.
|
||||
arg += '"'; //thats the post one.
|
||||
}
|
||||
|
||||
if (!st.empty())//first one does not need a preceding space
|
||||
if (!st.empty())//first one does not need a preceeding space
|
||||
st += ' ';
|
||||
|
||||
st += arg;
|
||||
|
||||
@@ -444,7 +444,7 @@ child executor<Sequence>::invoke(boost::mpl::false_, boost::mpl::false_)
|
||||
}
|
||||
if (_ec)
|
||||
{
|
||||
//if an error occurred we need to reap the child process
|
||||
//if an error occured we need to reap the child process
|
||||
::waitpid(this->pid, nullptr, WNOHANG);
|
||||
boost::fusion::for_each(seq, call_on_error(*this, _ec));
|
||||
return child();
|
||||
|
||||
@@ -80,7 +80,7 @@ struct io_context_ref : handler_base_ext
|
||||
void on_success(Executor& exec)
|
||||
{
|
||||
ios.notify_fork(boost::asio::io_context::fork_parent);
|
||||
//must be on the heap, so I can move it into the lambda.
|
||||
//must be on the heap so I can move it into the lambda.
|
||||
auto asyncs = boost::fusion::filter_if<
|
||||
is_async_handler<
|
||||
typename std::remove_reference< boost::mpl::_ > ::type
|
||||
|
||||
@@ -34,7 +34,7 @@ inline bool is_running(const child_handle &p, int & exit_code, std::error_code &
|
||||
|
||||
if (ret == -1)
|
||||
{
|
||||
if (errno != ECHILD) //because it no child is running, then this one isn't either, obviously.
|
||||
if (errno != ECHILD) //because it no child is running, than this one isn't either, obviously.
|
||||
ec = ::boost::process::detail::get_last_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -7,11 +7,8 @@
|
||||
#ifndef BOOST_PROCESS_DETAIL_POSIX_SIGCHLD_SERVICE_HPP_
|
||||
#define BOOST_PROCESS_DETAIL_POSIX_SIGCHLD_SERVICE_HPP_
|
||||
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/dispatch.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/consign.hpp>
|
||||
#include <boost/asio/append.hpp>
|
||||
#include <boost/asio/signal_set.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
@@ -29,43 +26,6 @@ class sigchld_service : public boost::asio::detail::service_base<sigchld_service
|
||||
|
||||
std::list<std::pair<::pid_t, std::function<void(int, std::error_code)>>> _receivers;
|
||||
inline void _handle_signal(const boost::system::error_code & ec);
|
||||
|
||||
struct initiate_async_wait_op
|
||||
{
|
||||
sigchld_service * self;
|
||||
template<typename Initiation>
|
||||
void operator()(Initiation && init, ::pid_t pid)
|
||||
{
|
||||
// check if the child actually is running first
|
||||
int status;
|
||||
auto pid_res = ::waitpid(pid, &status, WNOHANG);
|
||||
if (pid_res < 0)
|
||||
{
|
||||
auto ec = get_last_error();
|
||||
boost::asio::post(
|
||||
self->_strand,
|
||||
asio::append(std::forward<Initiation>(init), pid_res, ec));
|
||||
}
|
||||
else if ((pid_res == pid) && (WIFEXITED(status) || WIFSIGNALED(status)))
|
||||
boost::asio::post(
|
||||
self->_strand,
|
||||
boost::asio::append(std::forward<Initiation>(init), status, std::error_code{}));
|
||||
else //still running
|
||||
{
|
||||
sigchld_service * self_ = self;
|
||||
if (self->_receivers.empty())
|
||||
self->_signal_set.async_wait(
|
||||
boost::asio::bind_executor(
|
||||
self->_strand,
|
||||
[self_](const boost::system::error_code &ec, int)
|
||||
{
|
||||
self_->_handle_signal(ec);
|
||||
}));
|
||||
self->_receivers.emplace_back(pid, init);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
sigchld_service(boost::asio::io_context & io_context)
|
||||
: boost::asio::detail::service_base<sigchld_service>(io_context)
|
||||
@@ -77,10 +37,47 @@ public:
|
||||
void (int, std::error_code))
|
||||
async_wait(::pid_t pid, SignalHandler && handler)
|
||||
{
|
||||
return boost::asio::async_initiate<
|
||||
SignalHandler,
|
||||
void(int, std::error_code)>(
|
||||
initiate_async_wait_op{this}, handler, pid);
|
||||
boost::asio::async_completion<
|
||||
SignalHandler, void(boost::system::error_code)> init{handler};
|
||||
|
||||
auto & h = init.completion_handler;
|
||||
boost::asio::dispatch(
|
||||
_strand,
|
||||
[this, pid, h]
|
||||
{
|
||||
//check if the child actually is running first
|
||||
int status;
|
||||
auto pid_res = ::waitpid(pid, &status, WNOHANG);
|
||||
if (pid_res < 0)
|
||||
{
|
||||
auto ec = get_last_error();
|
||||
boost::asio::post(
|
||||
_strand,
|
||||
[pid_res, ec, h]
|
||||
{
|
||||
h(pid_res, ec);
|
||||
});
|
||||
}
|
||||
else if ((pid_res == pid) && (WIFEXITED(status) || WIFSIGNALED(status)))
|
||||
boost::asio::post(
|
||||
_strand,
|
||||
[status, h]
|
||||
{
|
||||
h(status, {}); //successfully exited already
|
||||
});
|
||||
else //still running
|
||||
{
|
||||
if (_receivers.empty())
|
||||
_signal_set.async_wait(
|
||||
[this](const boost::system::error_code &ec, int)
|
||||
{
|
||||
boost::asio::dispatch(_strand, [this, ec]{this->_handle_signal(ec);});
|
||||
});
|
||||
_receivers.emplace_back(pid, h);
|
||||
}
|
||||
});
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
void shutdown() override
|
||||
{
|
||||
|
||||
@@ -62,7 +62,7 @@ inline std::string build_args(const std::string & exe, std::vector<std::string>
|
||||
}
|
||||
}
|
||||
|
||||
if (!st.empty())//first one does not need a preceding space
|
||||
if (!st.empty())//first one does not need a preceeding space
|
||||
st += ' ';
|
||||
|
||||
st += arg;
|
||||
@@ -106,7 +106,7 @@ inline std::wstring build_args(const std::wstring & exe, std::vector<std::wstrin
|
||||
}
|
||||
}
|
||||
|
||||
if (!st.empty())//first one does not need a preceding space
|
||||
if (!st.empty())//first one does not need a preceeding space
|
||||
st += L' ';
|
||||
|
||||
st += arg;
|
||||
|
||||
@@ -81,7 +81,7 @@ struct child_handle
|
||||
{
|
||||
::boost::winapi::BOOL_ value;
|
||||
if (!::boost::winapi::IsProcessInJob(proc_info.hProcess, nullptr, &value))
|
||||
throw_last_error("IsProcessInJob Failed");
|
||||
throw_last_error("IsProcessinJob Failed");
|
||||
return value!=0;
|
||||
}
|
||||
bool in_group(std::error_code &ec) const noexcept
|
||||
|
||||
@@ -73,8 +73,8 @@ inline auto native_environment_impl<Char>::get(const pointer_type id) -> string_
|
||||
|
||||
if (size == sizeof(buf)) //the return size gives the size without the null, so I know this went wrong
|
||||
{
|
||||
/* limit defined here https://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx
|
||||
* but I used 32768, so it is a multiple of 4096.
|
||||
/*limit defined here https://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx
|
||||
* but I used 32768 so it is a multiple of 4096.
|
||||
*/
|
||||
constexpr static std::size_t max_size = 32768;
|
||||
//Handle variables longer then buf.
|
||||
@@ -232,7 +232,7 @@ basic_environment_impl<Char>::basic_environment_impl(const native_environment_im
|
||||
template<typename Char>
|
||||
inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type
|
||||
{
|
||||
if (id.size() >= _data.size()) //ok, so it is impossible id is in there.
|
||||
if (id.size() >= _data.size()) //ok, so it's impossible id is in there.
|
||||
return string_type(_data.data());
|
||||
|
||||
if (std::equal(id.begin(), id.end(), _data.begin()) && (_data[id.size()] == equal_sign<Char>()))
|
||||
@@ -273,7 +273,7 @@ template<typename Char>
|
||||
inline void basic_environment_impl<Char>::reset(const string_type &id)
|
||||
{
|
||||
//ok, we need to check the size of data first
|
||||
if (id.size() >= _data.size()) //ok, so it is impossible id is in there.
|
||||
if (id.size() >= _data.size()) //ok, so it's impossible id is in there.
|
||||
return;
|
||||
|
||||
//check if it's the first one, spares us the search.
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <boost/process/detail/windows/handler.hpp>
|
||||
#include <boost/winapi/get_current_process_id.hpp>
|
||||
#include <boost/winapi/handles.hpp>
|
||||
#include <boost/winapi/handle_info.hpp>
|
||||
|
||||
namespace boost { namespace process { namespace detail {
|
||||
|
||||
@@ -164,7 +163,7 @@ struct limit_handles_ : handler_base_ext
|
||||
}
|
||||
|
||||
template<typename Executor>
|
||||
void on_success(Executor & exec) const
|
||||
void on_sucess(Executor & exec) const
|
||||
{
|
||||
for (auto handle : handles_with_inherit_flag)
|
||||
::boost::winapi::SetHandleInformation(handle, ::boost::winapi::HANDLE_FLAG_INHERIT_, ::boost::winapi::HANDLE_FLAG_INHERIT_);
|
||||
|
||||
@@ -437,7 +437,7 @@ for both `id` and `value`.
|
||||
|
||||
\subsubsection env_reset Reset variables
|
||||
|
||||
Resetting single variables can be done in the following way:
|
||||
Reseting signle variables can be done in the following way:
|
||||
|
||||
\code{.cpp}
|
||||
env[id] = boost::none;
|
||||
|
||||
@@ -70,7 +70,7 @@ using ::boost::process::detail::get_used_handles;
|
||||
|
||||
///This handler is invoked before the process in launched, to setup parameters. The required signature is `void(Exec &)`, where `Exec` is a template parameter.
|
||||
constexpr boost::process::detail::make_handler_t<boost::process::detail::on_setup_> on_setup;
|
||||
///This handler is invoked if an error occurred. The required signature is `void(auto & exec, const std::error_code&)`, where `Exec` is a template parameter.
|
||||
///This handler is invoked if an error occured. The required signature is `void(auto & exec, const std::error_code&)`, where `Exec` is a template parameter.
|
||||
constexpr boost::process::detail::make_handler_t<boost::process::detail::on_error_> on_error;
|
||||
///This handler is invoked if launching the process has succeeded. The required signature is `void(auto & exec)`, where `Exec` is a template parameter.
|
||||
constexpr boost::process::detail::make_handler_t<boost::process::detail::on_success_> on_success;
|
||||
|
||||
@@ -82,7 +82,7 @@ using limit_handles_ = ::boost::process::detail::api::limit_handles_;
|
||||
}
|
||||
|
||||
/**
|
||||
* The limit_handles property sets all properties to be inherited only explicitly. It closes all unused file-descriptors on posix after the fork and
|
||||
* The limit_handles property sets all properties to be inherited only expcitly. It closes all unused file-descriptors on posix after the fork and
|
||||
* removes the inherit flags on windows.
|
||||
*
|
||||
* \note This is executed after the fork on posix.
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace boost {
|
||||
|
||||
namespace boost { namespace process {
|
||||
|
||||
///Namespace containing the posix extensions.
|
||||
///Namespace containing the posix exensions.
|
||||
namespace posix {
|
||||
|
||||
/** This property lets you modify file-descriptors other than the standard ones (0,1,2).
|
||||
|
||||
@@ -128,7 +128,7 @@ inline int get_cont_octet_out_count_impl<4>(wchar_t word) {
|
||||
|
||||
// Note that the following code will generate warnings on some platforms
|
||||
// where wchar_t is defined as UCS2. The warnings are superfluous as the
|
||||
// specialization is never instantiated with such compilers, but this
|
||||
// specialization is never instantitiated with such compilers, but this
|
||||
// can cause problems if warnings are being treated as errors, so we guard
|
||||
// against that. Including <boost/detail/utf8_codecvt_facet.hpp> as we do
|
||||
// should be enough to get WCHAR_MAX defined.
|
||||
|
||||
@@ -488,7 +488,7 @@ struct key
|
||||
using string_type = std::basic_string<char_type, traits_type>;
|
||||
using string_view_type = basic_string_view<char_type, traits_type>;
|
||||
|
||||
key() {}
|
||||
key() noexcept = default;
|
||||
key( const key& p ) = default;
|
||||
key( key&& p ) noexcept = default;
|
||||
key( const string_type& source ) : value_(source) {}
|
||||
@@ -524,11 +524,7 @@ struct key
|
||||
~key() = default;
|
||||
|
||||
key& operator=( const key& p ) = default;
|
||||
key& operator=( key&& p )
|
||||
{
|
||||
value_ = std::move(p.value_);
|
||||
return *this;
|
||||
}
|
||||
key& operator=( key&& p ) noexcept(std::is_nothrow_move_constructible<string_type>::value) = default;
|
||||
key& operator=( string_type&& source )
|
||||
{
|
||||
value_ = std::move(source);
|
||||
@@ -712,7 +708,7 @@ struct value
|
||||
using string_type = std::basic_string<char_type, traits_type>;
|
||||
using string_view_type = basic_cstring_ref<char_type, traits_type>;
|
||||
|
||||
value() {}
|
||||
value() noexcept = default;
|
||||
value( const value& p ) = default;
|
||||
|
||||
value( const string_type& source ) : value_(source) {}
|
||||
@@ -746,11 +742,7 @@ struct value
|
||||
~value() = default;
|
||||
|
||||
value& operator=( const value& p ) = default;
|
||||
value& operator=( value&& p )
|
||||
{
|
||||
value_ = std::move(p.value_);
|
||||
return *this;
|
||||
}
|
||||
value& operator=( value&& p ) noexcept(std::is_nothrow_move_constructible<string_type>::value) = default;
|
||||
value& operator=( string_type&& source )
|
||||
{
|
||||
value_ = std::move(source);
|
||||
@@ -943,7 +935,7 @@ struct key_value_pair
|
||||
using string_type = std::basic_string<char_type>;
|
||||
using string_view_type = basic_cstring_ref<char_type>;
|
||||
|
||||
key_value_pair() {}
|
||||
key_value_pair() noexcept = default;
|
||||
key_value_pair( const key_value_pair& p ) = default;
|
||||
key_value_pair( key_value_pair&& p ) noexcept = default;
|
||||
key_value_pair(key_view key, value_view value) : value_(key.basic_string<char_type, traits_type>() + equality_sign +
|
||||
@@ -1007,11 +999,7 @@ struct key_value_pair
|
||||
~key_value_pair() = default;
|
||||
|
||||
key_value_pair& operator=( const key_value_pair& p ) = default;
|
||||
key_value_pair& operator=( key_value_pair&& p )
|
||||
{
|
||||
value_ = std::move(p.value_);
|
||||
return *this;
|
||||
}
|
||||
key_value_pair& operator=( key_value_pair&& p ) noexcept(std::is_nothrow_move_constructible<string_type>::value) = default;
|
||||
key_value_pair& operator=( string_type&& source )
|
||||
{
|
||||
value_ = std::move(source);
|
||||
|
||||
@@ -22,7 +22,7 @@ BOOST_PROCESS_V2_BEGIN_NAMESPACE
|
||||
* @tparam Executor The asio executor of the process handle
|
||||
* @param proc The process to be run.
|
||||
* @return int The exit code of the process
|
||||
* @exception system_error An error that might have occurred during the wait.
|
||||
* @exception system_error An error that might have occured during the wait.
|
||||
*/
|
||||
template<typename Executor>
|
||||
inline int execute(basic_process<Executor> proc)
|
||||
@@ -92,13 +92,13 @@ struct execute_op
|
||||
/** This function asynchronously for a process to complete.
|
||||
*
|
||||
* Cancelling the execution will signal the child process to exit
|
||||
* with the following interpretations:
|
||||
* with the following intepretations:
|
||||
*
|
||||
* - cancellation_type::total -> interrupt
|
||||
* - cancellation_type::partial -> request_exit
|
||||
* - cancellation_type::terminal -> terminate
|
||||
*
|
||||
* It is to note that `async_execute` will us the lowest selected cancellation
|
||||
* It is to note that `async_execute` will us the lowest seelected cancellation
|
||||
* type. A subprocess might ignore anything not terminal.
|
||||
*/
|
||||
template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor,
|
||||
|
||||
@@ -147,14 +147,15 @@ std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
std::vector<pid_type> all_pids(boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<pid_type> vec;
|
||||
vec.resize(proc_listpids(PROC_ALL_PIDS, 0, nullptr, 0) / sizeof(pid_type));
|
||||
const auto sz = proc_listpids(PROC_ALL_PIDS, 0, &vec[0], sizeof(pid_type) * vec.size());
|
||||
if (sz < 0)
|
||||
vec.reserve(proc_listpids(PROC_ALL_PIDS, 0, nullptr, 0));
|
||||
if (proc_listpids(PROC_ALL_PIDS, 0, &vec[0], sizeof(pid_type) * vec.size()))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return {};
|
||||
}
|
||||
vec.resize(sz);
|
||||
auto itr = std::partition(vec.begin(), vec.end(), [](pid_type pt) {return pt != 0;});
|
||||
vec.erase(itr, vec.end());
|
||||
std::reverse(vec.begin(), vec.end());
|
||||
return vec;
|
||||
}
|
||||
|
||||
@@ -175,14 +176,15 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec)
|
||||
std::vector<pid_type> child_pids(pid_type pid, boost::system::error_code & ec)
|
||||
{
|
||||
std::vector<pid_type> vec;
|
||||
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)
|
||||
vec.reserve(proc_listpids(PROC_PPID_ONLY, (uint32_t)pid, nullptr, 0));
|
||||
if (proc_listpids(PROC_PPID_ONLY, (uint32_t)pid, &vec[0], sizeof(pid_type) * vec.size()))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
|
||||
return {};
|
||||
}
|
||||
vec.resize(sz);
|
||||
auto itr = std::partition(vec.begin(), vec.end(), [](pid_type pt) {return pt != 0;});
|
||||
vec.erase(itr, vec.end());
|
||||
std::reverse(vec.begin(), vec.end());
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ struct bind_fd
|
||||
*/
|
||||
bind_fd(int target, FILE * f) : bind_fd(target, fileno(f)) {}
|
||||
|
||||
/// Inherit a file descriptor with as a different value.
|
||||
/// Inherit a file descriptor with as a differnet value.
|
||||
/**
|
||||
* This will pass 24 as 42 to the child process:
|
||||
* @code
|
||||
@@ -79,7 +79,7 @@ struct bind_fd
|
||||
*/
|
||||
bind_fd(int target, std::nullptr_t) : bind_fd(target, filesystem::path("/dev/null")) {}
|
||||
|
||||
/// Inherit a newly opened-file as a set descriptor.
|
||||
/// Inherit a newly openedfile as a set descriptor.
|
||||
/**
|
||||
* This will pass 24 as 42 to the child process:
|
||||
* @code
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// boost/process/v2/posix/detail/close_handles.hpp
|
||||
// boost/process/v2/poxix/detail/close_handles.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
|
||||
|
||||
@@ -270,7 +270,7 @@ struct basic_process
|
||||
detail::throw_error(ec, "wait failed");
|
||||
return exit_code();
|
||||
}
|
||||
/// Waits for the process to exit, store the exit code internally and return it.
|
||||
/// Waits for the process to exit, store the exit code internall and return it.
|
||||
int wait(error_code & ec)
|
||||
{
|
||||
if (running(ec))
|
||||
|
||||
@@ -27,8 +27,8 @@ static const error_category& shell_category = get_shell_category();
|
||||
* In v1, this was possible directly when starting a process,
|
||||
* but has been removed based on the security risks associated with this.
|
||||
*
|
||||
* By making the shell parsing explicitly, it encourages
|
||||
* a user to run a sanity check on the executable before launching it.
|
||||
* By making the shell parsing explicity, it is encouraged
|
||||
* that a user runs a sanity check on the executable before launching it.
|
||||
*
|
||||
* @par Example
|
||||
* @code {.cpp}
|
||||
|
||||
@@ -265,7 +265,7 @@ typedef process_io_binding<STDERR_FILENO> process_error_binding;
|
||||
* - `FILE*` any open file, including `stdin`, `stdout` and `stderr`
|
||||
* - a filesystem::path, which will open a readable or writable depending on the direction of the stream
|
||||
* - `native_handle` any native file handle (`HANDLE` on windows) or file descriptor (`int` on posix)
|
||||
* - any io-object with a .native_handle() function that is compatible with the above. E.g. a asio::ip::tcp::socket
|
||||
* - any io-object with a .native_handle() function that is comptaiblie with the above. E.g. a asio::ip::tcp::socket
|
||||
* - an asio::basic_writeable_pipe for stdin or asio::basic_readable_pipe for stderr/stdout.
|
||||
*
|
||||
*
|
||||
|
||||
@@ -36,7 +36,7 @@ struct process_creation_flags
|
||||
};
|
||||
};
|
||||
|
||||
/// A flag to create a new process group. Necessary to allow interrupts for the subprocess.
|
||||
/// A flag to create a new process group. Necessary to allow interupts for the subproces.
|
||||
constexpr static process_creation_flags<CREATE_NEW_PROCESS_GROUP> create_new_process_group;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//
|
||||
// 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)
|
||||
// Created by kleme on 26.02.2018.
|
||||
//
|
||||
|
||||
#define BOOST_ASIO_NO_DEPRECATED 1
|
||||
#include <boost/process.hpp>
|
||||
|
||||
@@ -72,7 +72,7 @@ BOOST_AUTO_TEST_CASE(multithreaded_async_pipe)
|
||||
asio::io_context ioc;
|
||||
|
||||
std::vector<std::thread> threads;
|
||||
for (auto i = 0u; i < std::thread::hardware_concurrency(); i++)
|
||||
for (int i = 0; i < std::thread::hardware_concurrency(); i++)
|
||||
{
|
||||
threads.emplace_back([&ioc]
|
||||
{
|
||||
@@ -122,7 +122,7 @@ BOOST_AUTO_TEST_CASE(move_pipe)
|
||||
}
|
||||
/*
|
||||
{
|
||||
//copy a closed pipe
|
||||
//copy an a closed pipe
|
||||
BOOST_TEST_CHECKPOINT("Copy assign");
|
||||
BOOST_TEST_CHECKPOINT("Fourth move, from closed");
|
||||
bp::async_pipe ap_inv{ios};
|
||||
@@ -131,7 +131,7 @@ BOOST_AUTO_TEST_CASE(move_pipe)
|
||||
}
|
||||
|
||||
{
|
||||
//copy a closed pipe
|
||||
//copy an a closed pipe
|
||||
BOOST_TEST_CHECKPOINT("Copy assign");
|
||||
BOOST_TEST_CHECKPOINT("Fourth move, from closed");
|
||||
bp::async_pipe ap_inv{ios};
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace bp = boost::process;
|
||||
namespace fs = boost::process::filesystem;
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(explicit_)
|
||||
BOOST_AUTO_TEST_CASE(excplicit)
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(wait_group_test, *boost::unit_test::timeout(5))
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
BOOST_REQUIRE(c2.in_group(ec));
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
g.wait(ec);
|
||||
g.wait();
|
||||
|
||||
BOOST_CHECK(!c1.running());
|
||||
BOOST_CHECK(!c2.running());
|
||||
|
||||
@@ -59,11 +59,11 @@ test-suite standalone :
|
||||
[ run utf8.cpp test_impl ]
|
||||
[ run cstring_ref.cpp test_impl ]
|
||||
[ run environment.cpp test_impl ]
|
||||
[ run pid.cpp test_impl : : : <target-os>darwin:<build>no ]
|
||||
[ run shell.cpp test_impl ]
|
||||
;
|
||||
|
||||
test-suite with_target :
|
||||
[ run pid.cpp test_impl : --log_level=all --catch_system_errors=no -- : target ]
|
||||
[ run process.cpp test_impl : --log_level=all --catch_system_errors=no -- : target ]
|
||||
[ run windows.cpp test_impl : --log_level=all --catch_system_errors=no -- : target : <build>no <target-os>windows:<build>yes <target-os>windows:<source>Advapi32 ]
|
||||
[ run ext.cpp test_impl : --log_level=all --catch_system_errors=no -- : target : <target-os>darwin:<build>no ]
|
||||
|
||||
@@ -80,7 +80,7 @@ BOOST_AUTO_TEST_CASE(cmd_exe)
|
||||
BOOST_CHECK_EQUAL(bp2::detail::conv_string<char>(ref.data(), ref.size()), pth);
|
||||
|
||||
BOOST_REQUIRE_EQUAL(cm.argc(), args.size() + 1);
|
||||
for (auto i = 0u; i < args.size(); i++)
|
||||
for (auto i = 0; i < args.size(); i++)
|
||||
{
|
||||
ref = cm.argv()[i + 1];
|
||||
|
||||
|
||||
@@ -5,12 +5,10 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/process/v2/pid.hpp>
|
||||
#include <boost/process/v2/process.hpp>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_pid)
|
||||
@@ -24,30 +22,21 @@ BOOST_AUTO_TEST_CASE(test_pid)
|
||||
BOOST_CHECK_GT(all.size(), 0u);
|
||||
BOOST_CHECK(itr != all.end());
|
||||
|
||||
|
||||
std::vector<bp2::pid_type> children, grand_children;
|
||||
auto grand_child_pids = [](bp2::pid_type pid,
|
||||
std::vector<bp2::pid_type> & children,
|
||||
std::vector<bp2::pid_type> & grand_children)
|
||||
{
|
||||
children = bp2::child_pids(pid);
|
||||
for (unsigned i = 0; i < children.size(); i++)
|
||||
{
|
||||
std::vector<bp2::pid_type> tmp1;
|
||||
std::vector<bp2::pid_type> tmp2 = bp2::child_pids(children[i]);
|
||||
tmp1.insert(std::end(tmp1), std::begin(tmp2), std::end(tmp2));
|
||||
grand_children = tmp1;
|
||||
}
|
||||
return (!children.empty() || !grand_children.empty());
|
||||
};
|
||||
BOOST_CHECK_NE(grand_child_pids(bp2::root_pid, children, grand_children), false);
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(child_pid)
|
||||
{
|
||||
namespace bp2 = boost::process::v2;
|
||||
|
||||
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));
|
||||
|
||||
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));
|
||||
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());
|
||||
BOOST_CHECK(std::find(c2.begin(), c2.end(), proc.id()) != c2.end());
|
||||
proc.terminate();
|
||||
proc.wait();
|
||||
|
||||
auto c3 = bp2::child_pids(bp2::current_pid());
|
||||
BOOST_CHECK(std::find(c3.begin(), c3.end(), proc.id()) == c3.end());
|
||||
BOOST_CHECK_LT(c3.size(), c2.size());
|
||||
}
|
||||
@@ -424,11 +424,6 @@ BOOST_AUTO_TEST_CASE(print_other_cwd)
|
||||
|
||||
BOOST_CHECK(sz != 0);
|
||||
BOOST_CHECK_MESSAGE((ec == asio::error::broken_pipe) || (ec == asio::error::eof), ec.message());
|
||||
|
||||
|
||||
if (out.back() != '/' && target.string().back() == '/')
|
||||
out += '/';
|
||||
|
||||
BOOST_CHECK_MESSAGE(bpv::filesystem::path(out) == target,
|
||||
bpv::filesystem::path(out) << " != " << target);
|
||||
|
||||
@@ -558,10 +553,6 @@ BOOST_AUTO_TEST_CASE(bind_launcher)
|
||||
|
||||
BOOST_CHECK(sz != 0);
|
||||
BOOST_CHECK_MESSAGE((ec == asio::error::broken_pipe) || (ec == asio::error::eof), ec.message());
|
||||
|
||||
if (out.back() != '/' && target.string().back() == '/')
|
||||
out += '/';
|
||||
|
||||
BOOST_CHECK_MESSAGE(bpv::filesystem::path(out) == target,
|
||||
bpv::filesystem::path(out) << " != " << target);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user