mirror of
https://github.com/boostorg/process.git
synced 2026-01-22 05:22:37 +00:00
Compare commits
1 Commits
boost-1.70
...
asio_no_de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6abce365c5 |
185
.travis.yml
185
.travis.yml
@@ -10,6 +10,28 @@
|
||||
#
|
||||
# File revision #6
|
||||
|
||||
env:
|
||||
global:
|
||||
# Autodetect Boost branch by using the following code: - BRANCH_TO_TEST=$TRAVIS_BRANCH
|
||||
# or just directly specify it
|
||||
- BRANCH_TO_TEST=$TRAVIS_BRANCH
|
||||
|
||||
# Files, which coverage results must be ignored (files from other projects).
|
||||
# Example: - IGNORE_COVERAGE='*/boost/progress.hpp */filesystem/src/*'
|
||||
- IGNORE_COVERAGE=''
|
||||
|
||||
# Explicitly remove the following library from Boost. This may be usefull, if you're for example running Travis
|
||||
# from `Boost.DLL` repo, while Boost already has `dll`.
|
||||
#
|
||||
# By default is eaual to - BOOST_REMOVE=`basename $TRAVIS_BUILD_DIR`
|
||||
# This will force to use local repo content, instead of the Boost's default
|
||||
# not needed because process is not yet in boost.
|
||||
- BOOST_REMOVE=process
|
||||
|
||||
matrix:
|
||||
- CXX_STANDARD=c++11 TOOLSET=gcc-5
|
||||
- CXX_STANDARD=c++1y TOOLSET=gcc-5
|
||||
|
||||
|
||||
###############################################################################################################
|
||||
# From this point and below code is same for all the Boost libs
|
||||
@@ -17,120 +39,81 @@
|
||||
sudo: false
|
||||
language: cpp
|
||||
compiler:
|
||||
- gcc
|
||||
- gcc
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
secure: "vs7qgXb0lQg8CTyDPSi3RQtOIOtssaCkBIx86UoEvTXwJCTOLPe7ZufQ0lobn0OVWo261AMx9GbumBBzqfsvJc1G6ixGBVwymiGli/R8DZDvvg9UdljsEk65s/XbujE/9qh97zKGGioFyCn1Bmf5+SdDAxsuXTZm/cBny5VxYaaCR7s2cFUmp4up/djqg1GI7uwBh3ceodT3OL1X3dlMV59gOJWWNsB+RO9b9DPhTW7nOlMNRiEFik4rweecQB0JS8LaHDjYwzIRrGYHX+lR9cE/O8GCCHcUOmq9jCozDdxx+HZRu4rb1ST1RiDbvYaoeTif0Df1fVXHWOoO2D4NlXB6tJPXw2mkop00j6zkcydUJYid6T1lwfEpXAhd5A9FvOIXO5hoju1wlqfkU2eFQ9Na8z8bCIX2niZmveZWp4Ag52gEPzJMFx9hHGT8J4FWMvkqTWezux1sPZrjZjc0kXdJrIp84D9MsBc1sKrxOAOb5ekSfIK5n4JDkgUtuwMSTvEdWqNJXFPZq1rEu4GTwX99z3/XF+pM5XaCDQtZ/zUA5SPHhy0dKLH/BvceUqLJt53+lMcpsltJDB+XxQ/CFL7IdgR91OKGus/z4dbVWiSdkoNvcuZqjQLFLOMVNxoqC6PRvDAEhpy21j/5GUPvM5baQS7IEin0NF7bOTtXJdY="
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- BADGE=linux
|
||||
- BADGE=osx
|
||||
global:
|
||||
# Autodetect Boost branch by using the following code: - BRANCH_TO_TEST=$TRAVIS_BRANCH
|
||||
# or just directly specify it
|
||||
- BRANCH_TO_TEST=$TRAVIS_BRANCH
|
||||
|
||||
# Files, which coverage results must be ignored (files from other projects).
|
||||
# Example: - IGNORE_COVERAGE='*/boost/progress.hpp */filesystem/src/*'
|
||||
- IGNORE_COVERAGE=''
|
||||
|
||||
# Explicitly remove the following library from Boost. This may be usefull, if you're for example running Travis
|
||||
# from `Boost.DLL` repo, while Boost already has `dll`.
|
||||
#
|
||||
# By default is eaual to - BOOST_REMOVE=`basename $TRAVIS_BUILD_DIR`
|
||||
# This will force to use local repo content, instead of the Boost's default
|
||||
# not needed because process is not yet in boost.
|
||||
- BOOST_REMOVE=process
|
||||
- CXX_STANDARD=gnu++11
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- os: linux
|
||||
env: BADGE=osx
|
||||
- os: osx
|
||||
env: BADGE=linux
|
||||
|
||||
|
||||
- linux
|
||||
|
||||
# Installing additional tools
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- valgrind
|
||||
- python-yaml
|
||||
- gcc-5
|
||||
- g++-5
|
||||
# - lcov
|
||||
- clang
|
||||
- valgrind
|
||||
- python-yaml
|
||||
- gcc-5
|
||||
- g++-5
|
||||
# - lcov
|
||||
- clang
|
||||
|
||||
before_install:
|
||||
# Set this to the name of the library
|
||||
- PROJECT_TO_TEST=`basename $TRAVIS_BUILD_DIR`
|
||||
- echo "Testing $PROJECT_TO_TEST"
|
||||
- if [ $TRAVIS_OS_NAME = "osx" ]; then brew install gcc5; brew install valgrind; brew install llvm; TOOLSET=clang; BOOST_TEST_CATCH_SYSTEM_ERRORS=no; MULTITHREAD=-j8; else TOOLSET=gcc-5; USE_VALGRIND="testing.launcher=valgrind valgrind=on"; fi
|
||||
# Cloning Boost libraries (fast nondeep cloning)
|
||||
- BOOST=$HOME/boost-local
|
||||
- git init $BOOST
|
||||
- cd $BOOST
|
||||
- echo Branch to test $BRANCH_TO_TEST
|
||||
- if [ $BRANCH_TO_TEST = "master" ]; then
|
||||
BOOST_BRANCH=master;
|
||||
else BOOST_BRANCH=develop; fi
|
||||
- git remote add --no-tags -t $BOOST_BRANCH origin https://github.com/boostorg/boost.git
|
||||
- git fetch --depth=1
|
||||
- git checkout $BOOST_BRANCH
|
||||
- git submodule update --init --merge
|
||||
- git remote set-branches --add origin $BOOST_BRANCH
|
||||
- git pull --recurse-submodules
|
||||
- git submodule update --init
|
||||
- git checkout $BOOST_BRANCH
|
||||
- git submodule foreach "git reset --quiet --hard; git clean -fxd"
|
||||
- git reset --hard; git clean -fxd
|
||||
- git status
|
||||
- echo "Removing $BOOST/libs/$BOOST_REMOVE"
|
||||
- rm -rf $BOOST/libs/$BOOST_REMOVE
|
||||
- mv $TRAVIS_BUILD_DIR/../$PROJECT_TO_TEST/ $BOOST/libs/$PROJECT_TO_TEST
|
||||
- TRAVIS_BUILD_DIR=$BOOST/libs/$PROJECT_TO_TEST
|
||||
- ./bootstrap.sh
|
||||
- ./b2 headers
|
||||
- cd $BOOST/libs/$PROJECT_TO_TEST/test
|
||||
- echo BOOST_TEST_CATCH_SYSTEM_ERRORS $BOOST_TEST_CATCH_SYSTEM_ERRORS
|
||||
# Set this to the name of the library
|
||||
- PROJECT_TO_TEST=`basename $TRAVIS_BUILD_DIR`
|
||||
- echo "Testing $PROJECT_TO_TEST"
|
||||
# Cloning Boost libraries (fast nondeep cloning)
|
||||
- BOOST=$HOME/boost-local
|
||||
- git init $BOOST
|
||||
- cd $BOOST
|
||||
- if [ $BRANCH_TO_TEST = "master" ]; then
|
||||
BOOST_BRANCH=master;
|
||||
else BOOST_BRANCH=develop; fi
|
||||
- git remote add --no-tags -t $BOOST_BRANCH origin https://github.com/boostorg/boost.git
|
||||
- git fetch --depth=1
|
||||
- git checkout $BOOST_BRANCH
|
||||
- git submodule update --init --merge
|
||||
- git remote set-branches --add origin $BOOST_BRANCH
|
||||
- git pull --recurse-submodules
|
||||
- git submodule update --init
|
||||
- git checkout $BOOST_BRANCH
|
||||
- git submodule foreach "git reset --quiet --hard; git clean -fxd"
|
||||
- git reset --hard; git clean -fxd
|
||||
- git status
|
||||
- echo "Removing $BOOST/libs/$BOOST_REMOVE"
|
||||
- rm -rf $BOOST/libs/$BOOST_REMOVE
|
||||
- mv $TRAVIS_BUILD_DIR/../$PROJECT_TO_TEST/ $BOOST/libs/$PROJECT_TO_TEST
|
||||
- TRAVIS_BUILD_DIR=$BOOST/libs/$PROJECT_TO_TEST
|
||||
- ./bootstrap.sh
|
||||
- ./b2 headers
|
||||
- cd $BOOST/libs/$PROJECT_TO_TEST/test
|
||||
|
||||
script:
|
||||
# `--coverage` flags required to generate coverage info for Coveralls
|
||||
- ../../../b2 $MULTITHREAD with-valgrind address-model=64 architecture=x86 $USE_VALGRIND toolset=$TOOLSET cxxflags="--coverage -DBOOST_TRAVISCI_BUILD -std=$CXX_STANDARD" linkflags="--coverage" -sBOOST_BUILD_PATH=.
|
||||
- ../../../b2 $MULTITHREAD without-valgrind address-model=64 architecture=x86 toolset=$TOOLSET cxxflags="--coverage -DBOOST_TRAVISCI_BUILD -std=$CXX_STANDARD" linkflags="--coverage" -sBOOST_BUILD_PATH=.
|
||||
# `--coverage` flags required to generate coverage info for Coveralls
|
||||
- ../../../b2 with-valgrind address-model=64 architecture=x86 testing.launcher=valgrind valgrind=on toolset=$TOOLSET cxxflags="--coverage -DBOOST_TRAVISCI_BUILD -std=$CXX_STANDARD" linkflags="--coverage" -sBOOST_BUILD_PATH=.
|
||||
- ../../../b2 without-valgrind address-model=64 architecture=x86 toolset=$TOOLSET cxxflags="--coverage -DBOOST_TRAVISCI_BUILD -std=$CXX_STANDARD" linkflags="--coverage" -sBOOST_BUILD_PATH=.
|
||||
after_success:
|
||||
# Copying Coveralls data to a separate folder
|
||||
- mkdir -p $TRAVIS_BUILD_DIR/coverals
|
||||
- find ../../../bin.v2/ -name "*.gcda" -exec cp "{}" $TRAVIS_BUILD_DIR/coverals/ \;
|
||||
- find ../../../bin.v2/ -name "*.gcno" -exec cp "{}" $TRAVIS_BUILD_DIR/coverals/ \;
|
||||
# Copying Coveralls data to a separate folder
|
||||
- mkdir -p $TRAVIS_BUILD_DIR/coverals
|
||||
- find ../../../bin.v2/ -name "*.gcda" -exec cp "{}" $TRAVIS_BUILD_DIR/coverals/ \;
|
||||
- find ../../../bin.v2/ -name "*.gcno" -exec cp "{}" $TRAVIS_BUILD_DIR/coverals/ \;
|
||||
|
||||
# Preparing Coveralls data by changind data format to a readable one
|
||||
- git clone https://github.com/linux-test-project/lcov.git lcov_dir
|
||||
- GCOV_VERSION=""
|
||||
- if [[ "$TOOLSET" == *"-"* ]]; then GCOV_VERSION="--gcov-tool gcov-${TOOLSET#*-}"; fi
|
||||
- LCOV="$BOOST/libs/$PROJECT_TO_TEST/test/lcov_dir/bin/lcov $GCOV_VERSION"
|
||||
- $LCOV --directory $TRAVIS_BUILD_DIR/coverals --base-directory ./ --capture --output-file $TRAVIS_BUILD_DIR/coverals/coverage.info
|
||||
# Preparing Coveralls data by changind data format to a readable one
|
||||
- git clone https://github.com/linux-test-project/lcov.git lcov_dir
|
||||
- GCOV_VERSION=""
|
||||
- if [[ "$TOOLSET" == *"-"* ]]; then GCOV_VERSION="--gcov-tool gcov-${TOOLSET#*-}"; fi
|
||||
- LCOV="$BOOST/libs/$PROJECT_TO_TEST/test/lcov_dir/bin/lcov $GCOV_VERSION"
|
||||
- $LCOV --directory $TRAVIS_BUILD_DIR/coverals --base-directory ./ --capture --output-file $TRAVIS_BUILD_DIR/coverals/coverage.info
|
||||
|
||||
# ... erasing /test/ /example/ folder data
|
||||
- cd $BOOST
|
||||
- $LCOV --remove $TRAVIS_BUILD_DIR/coverals/coverage.info "*.cpp" "/usr*" "*/$PROJECT_TO_TEST/test/*" $IGNORE_COVERAGE "*/$PROJECT_TO_TEST/tests/*" "*/$PROJECT_TO_TEST/examples/*" "*/$PROJECT_TO_TEST/example/*" -o $TRAVIS_BUILD_DIR/coverals/coverage.info
|
||||
# ... erasing /test/ /example/ folder data
|
||||
- cd $BOOST
|
||||
- $LCOV --remove $TRAVIS_BUILD_DIR/coverals/coverage.info "/usr*" "*/$PROJECT_TO_TEST/test/*" $IGNORE_COVERAGE "*/$PROJECT_TO_TEST/tests/*" "*/$PROJECT_TO_TEST/examples/*" "*/$PROJECT_TO_TEST/example/*" -o $TRAVIS_BUILD_DIR/coverals/coverage.info
|
||||
|
||||
# ... erasing data that is not related to this project directly
|
||||
- OTHER_LIBS=`grep "submodule .*" .gitmodules | sed 's/\[submodule\ "\(.*\)"\]/"\*\/boost\/\1\.hpp" "\*\/boost\/\1\/\*"/g'| sed "/\"\*\/boost\/process\/\*\"/d" | sed ':a;N;$!ba;s/\n/ /g'`
|
||||
- echo $OTHER_LIBS
|
||||
- eval "$LCOV --remove $TRAVIS_BUILD_DIR/coverals/coverage.info $OTHER_LIBS -o $TRAVIS_BUILD_DIR/coverals/coverage.info" > /dev/null
|
||||
# ... erasing data that is not related to this project directly
|
||||
- OTHER_LIBS=`grep "submodule .*" .gitmodules | sed 's/\[submodule\ "\(.*\)"\]/"\*\/boost\/\1\.hpp" "\*\/boost\/\1\/\*"/g'| sed "/\"\*\/boost\/$PROJECT_TO_TEST\/\*\"/d" | sed ':a;N;$!ba;s/\n/ /g'`
|
||||
- echo $OTHER_LIBS
|
||||
- eval "$LCOV --remove $TRAVIS_BUILD_DIR/coverals/coverage.info $OTHER_LIBS -o $TRAVIS_BUILD_DIR/coverals/coverage.info"
|
||||
|
||||
# Sending data to Coveralls
|
||||
- cd $TRAVIS_BUILD_DIR
|
||||
- gem install coveralls-lcov
|
||||
- coveralls-lcov coverals/coverage.info
|
||||
|
||||
after_script:
|
||||
- curl -s https://report.ci/upload.py | python - --token=$REPORT_CI_TOKEN --name="$BADGE test run"
|
||||
# Sending data to Coveralls
|
||||
- cd $TRAVIS_BUILD_DIR
|
||||
- gem install coveralls-lcov
|
||||
- coveralls-lcov coverals/coverage.info
|
||||
|
||||
@@ -4,11 +4,10 @@ Boost.process is a library for comfortable management of processes, released wit
|
||||
|
||||
### Test results
|
||||
|
||||
Branches | Linux | OSX | Windows | Code coverage | Matrix |
|
||||
----------------|-------|-----|---------| ------------- |--------|
|
||||
Develop: | [](https://travis-ci.org/klemens-morgenstern/boost-process) [](https://api.report.ci/status/klemens-morgenstern/boost-process?branch=develop&build=linux) | [](https://travis-ci.org/klemens-morgenstern/boost-process) [](https://api.report.ci/status/klemens-morgenstern/boost-process?branch=develop&build=osx) | [](https://ci.appveyor.com/project/klemens-morgenstern/boost-process/branch/develop) [](https://api.report.ci/status/klemens-morgenstern/boost-process?branch=develop&build=windows) | [](https://coveralls.io/github/klemens-morgenstern/boost-process?branch=develop) | [](http://www.boost.org/development/tests/develop/developer/process.html)
|
||||
Master: | [](https://travis-ci.org/klemens-morgenstern/boost-process) [](https://api.report.ci/status/klemens-morgenstern/boost-process?branch=master&build=linux) | [](https://travis-ci.org/klemens-morgenstern/boost-process) [](https://api.report.ci/status/klemens-morgenstern/boost-process?branch=master&build=osx) | [](https://ci.appveyor.com/project/klemens-morgenstern/boost-process/branch/master) [](https://api.report.ci/status/klemens-morgenstern/boost-process?branch=master&build=windows) | [](https://coveralls.io/github/klemens-morgenstern/boost-process?branch=master) | [](http://www.boost.org/development/tests/master/developer/process.html)
|
||||
|
||||
Branches | Build | Tests coverage |
|
||||
----------------|-------------- | -------------- |
|
||||
Develop: | [](https://travis-ci.org/klemens-morgenstern/boost-process) [](https://ci.appveyor.com/project/klemens-morgenstern/boost-process) | [](https://coveralls.io/github/klemens-morgenstern/boost-process?branch=develop) |
|
||||
Master: | [](https://travis-ci.org/klemens-morgenstern/boost-process) [](https://ci.appveyor.com/project/klemens-morgenstern/boost-process/branch/master) | [](https://coveralls.io/github/klemens-morgenstern/boost-process?branch=master) |
|
||||
|
||||
[Open Issues](https://github.com/klemens-morgenstern/boost-process/issues)
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
[def __on_success__ [memberref boost::process::extend::handler::on_success on_success]]
|
||||
[def __posix_executor__ [classref boost::process::extend::posix_executor ex::posix_executor]]
|
||||
[def __windows_executor__ [classref boost::process::extend::windows_executor ex::windows_executor]]
|
||||
[def __io_context__ [@http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_context.html boost::asio::io_context]]
|
||||
[def __require_io_context__ [classref boost::process::extend::require_io_context ex::require_io_context]]
|
||||
[def io_service [@http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_service.html boost::asio::io_service]]
|
||||
[def __require_io_service__ [classref boost::process::extend::require_io_service ex::require_io_service]]
|
||||
[def __async_handler__ [classref boost::process::extend::async_handler ex::async_handler]]
|
||||
[def __get_io_context__ [funcref boost::process::extend::get_io_context ex::get_io_context]]
|
||||
[def __get_io_service__ [funcref boost::process::extend::get_io_service ex::get_io_service]]
|
||||
|
||||
[section:extend Extensions]
|
||||
To extend the library, the header [headerref boost/process/extend.hpp extend] is provided.
|
||||
@@ -50,7 +50,7 @@ So let's start with a simple hello-world example, while we use a C++14 generic l
|
||||
using namespace boost::process;
|
||||
namespace ex = bp::extend;
|
||||
|
||||
__child__ c("foo", __on_success__=[](auto & exec) {std::cout << "hello world" << std::endl;});
|
||||
__child__ c("foo", ex::__on_success__=[](auto & exec) {std::cout << "hello world" << std::endl;});
|
||||
```
|
||||
|
||||
Considering that lambda can also capture values, data can easily be shared between handlers.
|
||||
@@ -95,24 +95,24 @@ Every handler not implemented dafaults to [classref boost::process::extend::hand
|
||||
[section:async Asynchronous Functionality]
|
||||
|
||||
Since `boost.process` provides an interface for [@http://www.boost.org/doc/libs/release/libs/asio/ boost.asio],
|
||||
this functionality is also available for extensions. If the class needs the __io_context__ for some reason, the following code will do that.
|
||||
this functionality is also available for extensions. If the class needs the io_service for some reason, the following code will do that.
|
||||
|
||||
```
|
||||
struct async_foo : __handler__, __require_io_context__
|
||||
struct async_foo : __handler__, __require_io_service__
|
||||
{
|
||||
tempalte<typename Executor>
|
||||
void on_setup(Executor & exec)
|
||||
{
|
||||
__io_context__ & ios = __get_io_context__(exec.seq); //gives us a reference and a compiler error if not present.
|
||||
io_service & ios = __get_io_service__(exec.seq); //gives us a reference and a compiler error if not present.
|
||||
//do something with ios
|
||||
}
|
||||
};
|
||||
```
|
||||
[note Inheriting [globalref boost::process::extend::require_io_context require_io_context] is necessary, so [funcref boost::process::system system] provides one.]
|
||||
[note Inheriting [globalref boost::process::extend::require_io_service require_io_service] is necessary, so [funcref boost::process::system system] provides one.]
|
||||
|
||||
Additionally the handler can provide a function that is invoked when the child process exits. This is done through __async_handler__.
|
||||
|
||||
[note [globalref boost::process::extend::async_handler async_handler] implies [globalref boost::process::extend::require_io_context require_io_context] .]
|
||||
[note [globalref boost::process::extend::async_handler async_handler] implies [globalref boost::process::extend::require_io_service require_io_service] .]
|
||||
|
||||
```
|
||||
struct async_bar : __handler, __async_handler__
|
||||
@@ -120,8 +120,8 @@ struct async_bar : __handler, __async_handler__
|
||||
template<typename Executor>
|
||||
std::function<void(int, const std::error_code&)> on_exit_handler(Executor & exec)
|
||||
{
|
||||
auto handler_ = this->handler;
|
||||
return [handler_](int exit_code, const std::error_code & ec)
|
||||
auto handler = this->handler;
|
||||
return [handler](int exit_code, const std::error_code & ec)
|
||||
{
|
||||
std::cout << "hello world, I exited with " << exit_code << std::endl;
|
||||
};
|
||||
|
||||
@@ -158,7 +158,7 @@ will change the behaviour, so that instead of throwing an exception, the error w
|
||||
|
||||
```
|
||||
std::error_code ec;
|
||||
bp::system("g++ main.cpp", ec);
|
||||
bp::system c("g++ main.cpp", ec);
|
||||
```
|
||||
[endsect]
|
||||
[section:io Synchronous I/O]
|
||||
@@ -296,7 +296,7 @@ provided we also pass a reference to an io_service.
|
||||
|
||||
```
|
||||
io_service ios;
|
||||
std::vector<char> buf(4096);
|
||||
std::vector<char> buf;
|
||||
|
||||
bp::child c(bp::search_path("g++"), "main.cpp", bp::std_out > asio_buffer(buf), ios);
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
|
||||
import sys
|
||||
|
||||
for line in sys.stdin:
|
||||
# If line is a 'noisy' warning, don't print it or the following two lines.
|
||||
if ('warning: section' in line and 'is deprecated' in line
|
||||
or 'note: change section name to' in line):
|
||||
next(sys.stdin)
|
||||
next(sys.stdin)
|
||||
else:
|
||||
sys.stdout.write(line)
|
||||
sys.stdout.flush()
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <type_traits>
|
||||
#include <memory>
|
||||
#include <boost/asio/async_result.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <tuple>
|
||||
|
||||
@@ -65,12 +64,11 @@ struct async_system_handler : ::boost::process::detail::api::async_handler
|
||||
errored = true;
|
||||
#endif
|
||||
auto & h = init.completion_handler;
|
||||
boost::asio::post(
|
||||
ios.get_executor(),
|
||||
[h, ec]() mutable
|
||||
{
|
||||
h(boost::system::error_code(ec.value(), boost::system::system_category()), -1);
|
||||
});
|
||||
ios.post(
|
||||
[h, ec]() mutable
|
||||
{
|
||||
h(boost::system::error_code(ec.value(), boost::system::system_category()), -1);
|
||||
});
|
||||
}
|
||||
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(ExitHandler, void (boost::system::error_code, int))
|
||||
@@ -84,7 +82,7 @@ struct async_system_handler : ::boost::process::detail::api::async_handler
|
||||
{
|
||||
#if defined(BOOST_POSIX_API)
|
||||
if (errored)
|
||||
return [](int , const std::error_code &){};
|
||||
return [](int exit_code, const std::error_code & ec){};
|
||||
#endif
|
||||
auto & h = init.completion_handler;
|
||||
return [h](int exit_code, const std::error_code & ec) mutable
|
||||
|
||||
@@ -92,10 +92,6 @@ class child
|
||||
/** Get the Process Identifier. */
|
||||
pid_t id() const;
|
||||
|
||||
/** Get the native, uninterpreted exit code. The return value is without any meaning if the child wasn't waited
|
||||
* for or if it was terminated. */
|
||||
int native_exit_code() const;
|
||||
|
||||
/** Check if the child process is running. */
|
||||
bool running();
|
||||
/** \overload void running() */
|
||||
|
||||
@@ -101,8 +101,6 @@ public:
|
||||
int exit_code() const {return ::boost::process::detail::api::eval_exit_status(_exit_status->load());}
|
||||
pid_t id() const {return _child_handle.id(); }
|
||||
|
||||
int native_exit_code() const {return _exit_status->load();}
|
||||
|
||||
bool running()
|
||||
{
|
||||
std::error_code ec;
|
||||
|
||||
@@ -57,10 +57,6 @@ inline std::error_code get_last_error() noexcept
|
||||
#define BOOST_POSIX_HAS_VFORK 1
|
||||
#endif
|
||||
|
||||
#if (_POSIX_C_SOURCE >= 199309L)
|
||||
#define BOOST_POSIX_HAS_SIGTIMEDWAIT 1
|
||||
#endif
|
||||
|
||||
#elif defined(BOOST_WINDOWS_API)
|
||||
namespace windows {namespace extensions {}}
|
||||
namespace api = windows;
|
||||
|
||||
@@ -22,8 +22,6 @@ class basic_streambuf;
|
||||
typedef basic_streambuf<std::allocator<char>> streambuf;
|
||||
class io_context;
|
||||
|
||||
class executor;
|
||||
|
||||
|
||||
#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
|
||||
class signal_set_service;
|
||||
@@ -32,9 +30,7 @@ template <typename SignalSetService>
|
||||
class basic_signal_set;
|
||||
typedef basic_signal_set<signal_set_service> signal_set;
|
||||
#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
|
||||
template <typename Executor>
|
||||
class basic_signal_set;
|
||||
typedef basic_signal_set<executor> signal_set;
|
||||
class signal_set;
|
||||
#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
|
||||
|
||||
template <typename Handler>
|
||||
@@ -49,9 +45,7 @@ template <typename StreamDesscriptorService>
|
||||
class basic_stream_descriptor;
|
||||
typedef basic_stream_descriptor<stream_descriptor_service> stream_descriptor;
|
||||
#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
|
||||
template <typename Executor>
|
||||
class basic_stream_descriptor;
|
||||
typedef basic_stream_descriptor<executor> stream_descriptor;
|
||||
class stream_descriptor;
|
||||
#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
|
||||
|
||||
} //posix
|
||||
|
||||
@@ -39,30 +39,30 @@ struct async_in_buffer : ::boost::process::detail::posix::handler_base_ext,
|
||||
{
|
||||
}
|
||||
template <typename Executor>
|
||||
inline void on_success(Executor)
|
||||
inline void on_success(Executor &exec)
|
||||
{
|
||||
auto pipe_ = this->pipe;
|
||||
auto pipe = this->pipe;
|
||||
if (this->promise)
|
||||
{
|
||||
auto promise_ = this->promise;
|
||||
auto promise = this->promise;
|
||||
|
||||
boost::asio::async_write(*pipe_, buf,
|
||||
[pipe_, promise_](const boost::system::error_code & ec, std::size_t)
|
||||
boost::asio::async_write(*pipe, buf,
|
||||
[pipe, promise](const boost::system::error_code & ec, std::size_t)
|
||||
{
|
||||
if (ec && (ec.value() != EBADF) && (ec.value() != EPERM) && (ec.value() != ENOENT))
|
||||
{
|
||||
std::error_code e(ec.value(), std::system_category());
|
||||
promise_->set_exception(std::make_exception_ptr(process_error(e)));
|
||||
promise->set_exception(std::make_exception_ptr(process_error(e)));
|
||||
}
|
||||
else
|
||||
promise_->set_value();
|
||||
promise->set_value();
|
||||
});
|
||||
}
|
||||
else
|
||||
boost::asio::async_write(*pipe_, buf,
|
||||
[pipe_](const boost::system::error_code&, std::size_t){});
|
||||
boost::asio::async_write(*pipe, buf,
|
||||
[pipe](const boost::system::error_code&ec, std::size_t size){});
|
||||
|
||||
std::move(*pipe_).source().close();
|
||||
std::move(*pipe).source().close();
|
||||
|
||||
this->pipe = nullptr;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ struct async_out_buffer : ::boost::process::detail::posix::handler_base_ext,
|
||||
{
|
||||
auto pipe = this->pipe;
|
||||
boost::asio::async_read(*pipe, buf,
|
||||
[pipe](const boost::system::error_code&, std::size_t){});
|
||||
[pipe](const boost::system::error_code&, std::size_t size){});
|
||||
|
||||
this->pipe = nullptr;
|
||||
std::move(*pipe).sink().close();
|
||||
@@ -112,32 +112,32 @@ struct async_out_future : ::boost::process::detail::posix::handler_base_ext,
|
||||
fut = promise->get_future();
|
||||
}
|
||||
template <typename Executor>
|
||||
inline void on_success(Executor &)
|
||||
inline void on_success(Executor &exec)
|
||||
{
|
||||
auto pipe_ = this->pipe;
|
||||
auto pipe = this->pipe;
|
||||
|
||||
auto buffer_ = this->buffer;
|
||||
auto promise_ = this->promise;
|
||||
auto buffer = this->buffer;
|
||||
auto promise = this->promise;
|
||||
|
||||
boost::asio::async_read(*pipe_, *buffer_,
|
||||
[pipe_, buffer_, promise_](const boost::system::error_code& ec, std::size_t)
|
||||
boost::asio::async_read(*pipe, *buffer,
|
||||
[pipe, buffer, promise](const boost::system::error_code& ec, std::size_t size)
|
||||
{
|
||||
if (ec && (ec.value() != ENOENT))
|
||||
{
|
||||
std::error_code e(ec.value(), std::system_category());
|
||||
promise_->set_exception(std::make_exception_ptr(process_error(e)));
|
||||
promise->set_exception(std::make_exception_ptr(process_error(e)));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::istream is (buffer_.get());
|
||||
std::istream is (buffer.get());
|
||||
Type arg;
|
||||
arg.resize(buffer_->size());
|
||||
is.read(&*arg.begin(), buffer_->size());
|
||||
promise_->set_value(std::move(arg));
|
||||
arg.resize(buffer->size());
|
||||
is.read(&*arg.begin(), buffer->size());
|
||||
promise->set_value(std::move(arg));
|
||||
}
|
||||
});
|
||||
|
||||
std::move(*pipe_).sink().close();
|
||||
std::move(*pipe).sink().close();
|
||||
this->pipe = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
#include <boost/process/detail/posix/basic_pipe.hpp>
|
||||
#include <boost/asio/posix/stream_descriptor.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <system_error>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@@ -110,9 +109,9 @@ public:
|
||||
void async_close()
|
||||
{
|
||||
if (_sink.is_open())
|
||||
boost::asio::post(_sink.get_executor(), [this]{_sink.close();});
|
||||
_sink.get_io_context(). post([this]{_sink.close();});
|
||||
if (_source.is_open())
|
||||
boost::asio::post(_source.get_executor(), [this]{_source.close();});
|
||||
_source.get_io_context().post([this]{_source.close();});
|
||||
}
|
||||
|
||||
template<typename MutableBufferSequence>
|
||||
@@ -126,18 +125,6 @@ public:
|
||||
return _sink.write_some(buffers);
|
||||
}
|
||||
|
||||
template<typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept
|
||||
{
|
||||
return _source.read_some(buffers, ec);
|
||||
}
|
||||
template<typename MutableBufferSequence>
|
||||
std::size_t write_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept
|
||||
{
|
||||
return _sink.write_some(buffers, ec);
|
||||
}
|
||||
|
||||
|
||||
native_handle_type native_source() const {return const_cast<boost::asio::posix::stream_descriptor&>(_source).native_handle();}
|
||||
native_handle_type native_sink () const {return const_cast<boost::asio::posix::stream_descriptor&>(_sink ).native_handle();}
|
||||
|
||||
@@ -149,7 +136,7 @@ public:
|
||||
const MutableBufferSequence & buffers,
|
||||
ReadHandler &&handler)
|
||||
{
|
||||
return _source.async_read_some(buffers, std::forward<ReadHandler>(handler));
|
||||
_source.async_read_some(buffers, std::forward<ReadHandler>(handler));
|
||||
}
|
||||
|
||||
template<typename ConstBufferSequence,
|
||||
@@ -160,7 +147,7 @@ public:
|
||||
const ConstBufferSequence & buffers,
|
||||
WriteHandler&& handler)
|
||||
{
|
||||
return _sink.async_write_some(buffers, std::forward<WriteHandler>(handler));
|
||||
_sink.async_write_some(buffers, std::forward<WriteHandler>(handler));
|
||||
}
|
||||
|
||||
|
||||
@@ -219,8 +206,8 @@ async_pipe::async_pipe(boost::asio::io_context & ios_source,
|
||||
}
|
||||
|
||||
async_pipe::async_pipe(const async_pipe & p) :
|
||||
_source(const_cast<async_pipe&>(p)._source.get_executor()),
|
||||
_sink( const_cast<async_pipe&>(p)._sink.get_executor())
|
||||
_source(const_cast<async_pipe&>(p)._source.get_io_context()),
|
||||
_sink( const_cast<async_pipe&>(p)._sink.get_io_context())
|
||||
{
|
||||
|
||||
//cannot get the handle from a const object.
|
||||
@@ -251,8 +238,8 @@ async_pipe& async_pipe::operator=(const async_pipe & p)
|
||||
int sink;
|
||||
|
||||
//cannot get the handle from a const object.
|
||||
auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(p._source).native_handle();
|
||||
auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(p._sink).native_handle();
|
||||
auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native_handle();
|
||||
auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native_handle();
|
||||
if (source_in == -1)
|
||||
source = -1;
|
||||
else
|
||||
|
||||
@@ -45,7 +45,7 @@ inline int execvpe(const char* filename, char * const arg_list[], char* env[])
|
||||
|
||||
if (e != nullptr)
|
||||
{
|
||||
std::vector<std::string> path;
|
||||
std::vector<std::string> path;
|
||||
boost::split(path, *e, boost::is_any_of(":"));
|
||||
|
||||
for (const std::string & pp : path)
|
||||
@@ -85,7 +85,7 @@ struct on_error_t
|
||||
template<typename T>
|
||||
void operator()(T & t) const
|
||||
{
|
||||
t.on_error(exec, error);
|
||||
t.on_error(exec, error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -157,13 +157,13 @@ struct on_fork_success_t
|
||||
};
|
||||
|
||||
template<typename Executor> on_setup_t <Executor> call_on_setup (Executor & exec) {return exec;}
|
||||
template<typename Executor> on_error_t <Executor> call_on_error (Executor & exec, const std::error_code & ec)
|
||||
template<typename Executor> on_error_t <Executor> call_on_error (Executor & exec, const std::error_code & ec)
|
||||
{
|
||||
return on_error_t<Executor> (exec, ec);
|
||||
}
|
||||
template<typename Executor> on_success_t<Executor> call_on_success(Executor & exec) {return exec;}
|
||||
|
||||
template<typename Executor> on_fork_error_t <Executor> call_on_fork_error (Executor & exec, const std::error_code & ec)
|
||||
template<typename Executor> on_fork_error_t <Executor> call_on_fork_error (Executor & exec, const std::error_code & ec)
|
||||
{
|
||||
return on_fork_error_t<Executor> (exec, ec);
|
||||
}
|
||||
@@ -293,14 +293,10 @@ class executor
|
||||
auto err = errno;
|
||||
if ((err == EBADF) || (err == EPERM))//that should occur on success, therefore return.
|
||||
return;
|
||||
//EAGAIN not yet forked, EINTR interrupted, i.e. try again
|
||||
//EAGAIN not yet forked, EINTR interrupted, i.e. try again
|
||||
else if ((err != EAGAIN ) && (err != EINTR))
|
||||
{
|
||||
::close(source);
|
||||
set_error(std::error_code(err, std::system_category()), "Error read pipe");
|
||||
}
|
||||
}
|
||||
::close(source);
|
||||
set_error(ec, std::move(msg));
|
||||
}
|
||||
|
||||
@@ -380,10 +376,7 @@ child executor<Sequence>::invoke(boost::mpl::false_, boost::mpl::false_)
|
||||
}
|
||||
if (::fcntl(p[1], F_SETFD, FD_CLOEXEC) == -1)
|
||||
{
|
||||
auto err = ::boost::process::detail::get_last_error();
|
||||
::close(p[0]);
|
||||
::close(p[1]);
|
||||
set_error(err, "fcntl(2) failed");
|
||||
set_error(::boost::process::detail::get_last_error(), "fcntl(2) failed");
|
||||
return child();
|
||||
}
|
||||
_ec.clear();
|
||||
@@ -427,8 +420,11 @@ child executor<Sequence>::invoke(boost::mpl::false_, boost::mpl::false_)
|
||||
|
||||
child c(child_handle(pid), exit_status);
|
||||
|
||||
|
||||
|
||||
::close(p[1]);
|
||||
_read_error(p[0]);
|
||||
::close(p[0]);
|
||||
|
||||
if (_ec)
|
||||
{
|
||||
|
||||
@@ -56,7 +56,7 @@ struct group_handle
|
||||
{
|
||||
return ::getpgid(proc) == grp;
|
||||
}
|
||||
bool has(handle_t proc, std::error_code &) noexcept
|
||||
bool has(handle_t proc, std::error_code & ec) noexcept
|
||||
{
|
||||
return ::getpgid(proc) == grp;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ struct async_handler_collector
|
||||
void operator()(T & t) const
|
||||
{
|
||||
handlers.push_back(t.on_exit_handler(exec));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
//Also set's up waiting for the exit, so it can close async stuff.
|
||||
@@ -79,7 +79,6 @@ struct io_context_ref : handler_base_ext
|
||||
template <class Executor>
|
||||
void on_success(Executor& exec)
|
||||
{
|
||||
ios.notify_fork(boost::asio::io_context::fork_parent);
|
||||
//must be on the heap so I can move it into the lambda.
|
||||
auto asyncs = boost::fusion::filter_if<
|
||||
is_async_handler<
|
||||
@@ -106,15 +105,6 @@ struct io_context_ref : handler_base_ext
|
||||
sigchld_service.async_wait(exec.pid, std::move(wh));
|
||||
}
|
||||
|
||||
template<typename Executor>
|
||||
void on_setup (Executor &) const {/*ios.notify_fork(boost::asio::io_context::fork_prepare);*/}
|
||||
|
||||
template<typename Executor>
|
||||
void on_exec_setup (Executor &) const {/*ios.notify_fork(boost::asio::io_context::fork_child);*/}
|
||||
|
||||
template <class Executor>
|
||||
void on_error(Executor&, const std::error_code &) const {/*ios.notify_fork(boost::asio::io_context::fork_parent);*/}
|
||||
|
||||
private:
|
||||
boost::asio::io_context &ios;
|
||||
boost::process::detail::posix::sigchld_service &sigchld_service = boost::asio::use_service<boost::process::detail::posix::sigchld_service>(ios);
|
||||
|
||||
@@ -16,11 +16,8 @@ namespace boost { namespace process { namespace detail { namespace posix {
|
||||
// Use the "stopped" state (WIFSTOPPED) to indicate "not terminated".
|
||||
// This bit arrangement of status codes is not guaranteed by POSIX, but (according to comments in
|
||||
// the glibc <bits/waitstatus.h> header) is the same across systems in practice.
|
||||
constexpr int still_active = 0x017f;
|
||||
static_assert(WIFSTOPPED(still_active), "Expected still_active to indicate WIFSTOPPED");
|
||||
static_assert(!WIFEXITED(still_active), "Expected still_active to not indicate WIFEXITED");
|
||||
static_assert(!WIFSIGNALED(still_active), "Expected still_active to not indicate WIFSIGNALED");
|
||||
static_assert(!WIFCONTINUED(still_active), "Expected still_active to not indicate WIFCONTINUED");
|
||||
constexpr int still_active = 0x7F;
|
||||
static_assert(!WIFEXITED(still_active) && !WIFSIGNALED(still_active), "Internal Error");
|
||||
|
||||
inline bool is_running(int code)
|
||||
{
|
||||
|
||||
@@ -27,7 +27,7 @@ struct on_exit_ : boost::process::detail::posix::async_handler
|
||||
{
|
||||
return handler;
|
||||
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
#ifndef BOOST_PROCESS_DETAIL_POSIX_SIGCHLD_SERVICE_HPP_
|
||||
#define BOOST_PROCESS_DETAIL_POSIX_SIGCHLD_SERVICE_HPP_
|
||||
|
||||
#include <boost/asio/dispatch.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/signal_set.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
@@ -38,34 +36,22 @@ public:
|
||||
{
|
||||
boost::asio::async_completion<
|
||||
SignalHandler, void(boost::system::error_code)> init{handler};
|
||||
|
||||
auto & h = init.completion_handler;
|
||||
boost::asio::dispatch(
|
||||
_strand,
|
||||
_strand.post(
|
||||
[this, pid, h]
|
||||
{
|
||||
//check if the child actually is running first
|
||||
int status;
|
||||
auto pid_res = ::waitpid(pid, &status, WNOHANG);
|
||||
if (pid_res < 0)
|
||||
h(-1, get_last_error());
|
||||
else if ((pid_res == pid) && (WIFEXITED(status) || WIFSIGNALED(status)))
|
||||
h(status, {}); //successfully exited already
|
||||
else //still running
|
||||
{
|
||||
if (_receivers.empty())
|
||||
_signal_set.async_wait(
|
||||
[this](const boost::system::error_code &ec, int)
|
||||
{
|
||||
boost::asio::dispatch(_strand, [this, ec]{this->_handle_signal(ec);});
|
||||
});
|
||||
_receivers.emplace_back(pid, h);
|
||||
}
|
||||
if (_receivers.empty())
|
||||
_signal_set.async_wait(
|
||||
[this](const boost::system::error_code & ec, int)
|
||||
{
|
||||
_strand.post([this,ec]{this->_handle_signal(ec);});
|
||||
});
|
||||
_receivers.emplace_back(pid, h);
|
||||
});
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
void shutdown() override
|
||||
void shutdown_service() override
|
||||
{
|
||||
_receivers.clear();
|
||||
}
|
||||
@@ -118,7 +104,8 @@ void sigchld_service::_handle_signal(const boost::system::error_code & ec)
|
||||
_signal_set.async_wait(
|
||||
[this](const boost::system::error_code & ec, int)
|
||||
{
|
||||
boost::asio::post(_strand, [this, ec]{this->_handle_signal(ec);});
|
||||
_strand.post([ec]{});
|
||||
this->_handle_signal(ec);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,7 @@ inline void wait(const child_handle &p, int & exit_code, std::error_code &ec) no
|
||||
{
|
||||
ret = ::waitpid(p.pid, &status, 0);
|
||||
}
|
||||
while (((ret == -1) && (errno == EINTR)) ||
|
||||
(ret != -1 && !WIFEXITED(status) && !WIFSIGNALED(status)));
|
||||
while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status) && !WIFSIGNALED(status)));
|
||||
|
||||
if (ret == -1)
|
||||
ec = boost::process::detail::get_last_error();
|
||||
@@ -54,43 +53,14 @@ inline bool wait_until(
|
||||
const std::chrono::time_point<Clock, Duration>& time_out,
|
||||
std::error_code & ec) noexcept
|
||||
{
|
||||
|
||||
::sigset_t sigset;
|
||||
|
||||
sigemptyset(&sigset);
|
||||
sigaddset(&sigset, SIGCHLD);
|
||||
|
||||
auto get_timespec =
|
||||
[](const Duration & dur)
|
||||
{
|
||||
::timespec ts;
|
||||
ts.tv_sec = std::chrono::duration_cast<std::chrono::seconds>(dur).count();
|
||||
ts.tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(dur).count() % 1000000000;
|
||||
return ts;
|
||||
};
|
||||
|
||||
pid_t ret;
|
||||
int status;
|
||||
|
||||
struct ::sigaction old_sig;
|
||||
if (-1 == ::sigaction(SIGCHLD, nullptr, &old_sig))
|
||||
{
|
||||
ec = get_last_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool timed_out;
|
||||
#if defined(BOOST_POSIX_HAS_SIGTIMEDWAIT)
|
||||
|
||||
do
|
||||
{
|
||||
auto ts = get_timespec(time_out - Clock::now());
|
||||
auto ret_sig = ::sigtimedwait(&sigset, nullptr, &ts);
|
||||
errno = 0;
|
||||
ret = ::waitpid(p.pid, &status, WNOHANG);
|
||||
|
||||
if ((ret_sig == SIGCHLD) && (old_sig.sa_handler != SIG_DFL) && (old_sig.sa_handler != SIG_IGN))
|
||||
old_sig.sa_handler(ret);
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
timed_out = Clock::now() >= time_out;
|
||||
@@ -101,61 +71,6 @@ inline bool wait_until(
|
||||
while ((ret == 0) ||
|
||||
(((ret == -1) && errno == EINTR) ||
|
||||
((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))));
|
||||
#else
|
||||
//if we do not have sigtimedwait, we fork off a child process to get the signal in time
|
||||
pid_t timeout_pid = ::fork();
|
||||
if (timeout_pid == -1)
|
||||
{
|
||||
ec = boost::process::detail::get_last_error();
|
||||
return true;
|
||||
}
|
||||
else if (timeout_pid == 0)
|
||||
{
|
||||
auto ts = get_timespec(time_out - Clock::now());
|
||||
::timespec rem;
|
||||
::nanosleep(&ts, &rem);
|
||||
while (rem.tv_sec > 0 || rem.tv_nsec > 0)
|
||||
::nanosleep(&rem, &rem);
|
||||
::exit(0);
|
||||
}
|
||||
|
||||
struct child_cleaner_t
|
||||
{
|
||||
pid_t pid;
|
||||
~child_cleaner_t()
|
||||
{
|
||||
int res;
|
||||
::kill(pid, -15);
|
||||
::waitpid(pid, &res, WNOHANG);
|
||||
}
|
||||
};
|
||||
child_cleaner_t child_cleaner{timeout_pid};
|
||||
|
||||
do
|
||||
{
|
||||
int ret_sig = 0;
|
||||
if ((::waitpid(timeout_pid, &status, WNOHANG) != 0)
|
||||
&& (WIFEXITED(status) || WIFSIGNALED(status)))
|
||||
ret_sig = ::sigwait(&sigset, nullptr);
|
||||
errno = 0;
|
||||
|
||||
ret = ::waitpid(p.pid, &status, WNOHANG);
|
||||
|
||||
if ((ret_sig == SIGCHLD) &&
|
||||
(old_sig.sa_handler != SIG_DFL) && (old_sig.sa_handler != SIG_IGN))
|
||||
old_sig.sa_handler(ret);
|
||||
|
||||
if (ret <= 0)
|
||||
{
|
||||
timed_out = Clock::now() >= time_out;
|
||||
if (timed_out)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
while ((ret == 0) ||
|
||||
(((ret == -1) && errno == EINTR) ||
|
||||
((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))));
|
||||
#endif
|
||||
|
||||
if (ret == -1)
|
||||
ec = boost::process::detail::get_last_error();
|
||||
@@ -172,7 +87,7 @@ template< class Clock, class Duration >
|
||||
inline bool wait_until(
|
||||
const child_handle &p,
|
||||
int & exit_code,
|
||||
const std::chrono::time_point<Clock, Duration>& time_out)
|
||||
const std::chrono::time_point<Clock, Duration>& time_out) noexcept
|
||||
{
|
||||
std::error_code ec;
|
||||
bool b = wait_until(p, exit_code, time_out, ec);
|
||||
@@ -194,7 +109,7 @@ template< class Rep, class Period >
|
||||
inline bool wait_for(
|
||||
const child_handle &p,
|
||||
int & exit_code,
|
||||
const std::chrono::duration<Rep, Period>& rel_time)
|
||||
const std::chrono::duration<Rep, Period>& rel_time) noexcept
|
||||
{
|
||||
std::error_code ec;
|
||||
bool b = wait_for(p, exit_code, rel_time, ec);
|
||||
|
||||
@@ -16,30 +16,21 @@
|
||||
#include <system_error>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace boost { namespace process { namespace detail { namespace posix {
|
||||
|
||||
inline void wait(const group_handle &p, std::error_code &ec) noexcept
|
||||
{
|
||||
pid_t ret;
|
||||
siginfo_t status;
|
||||
int status;
|
||||
|
||||
do
|
||||
{
|
||||
ret = ::waitpid(-p.grp, &status.si_status, 0);
|
||||
if (ret == -1)
|
||||
{
|
||||
ec = get_last_error();
|
||||
return;
|
||||
}
|
||||
|
||||
//ECHILD --> no child processes left.
|
||||
ret = ::waitid(P_PGID, p.grp, &status, WEXITED | WNOHANG);
|
||||
ret = ::waitpid(-p.grp, &status, 0);
|
||||
}
|
||||
while ((ret != -1) || (errno != ECHILD));
|
||||
|
||||
if (errno != ECHILD)
|
||||
while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status) && !WIFSIGNALED(status)));
|
||||
|
||||
if (ret == -1)
|
||||
ec = boost::process::detail::get_last_error();
|
||||
else
|
||||
ec.clear();
|
||||
@@ -58,120 +49,31 @@ inline bool wait_until(
|
||||
const std::chrono::time_point<Clock, Duration>& time_out,
|
||||
std::error_code & ec) noexcept
|
||||
{
|
||||
pid_t ret;
|
||||
int status;
|
||||
|
||||
::sigset_t sigset;
|
||||
::siginfo_t siginfo;
|
||||
|
||||
sigemptyset(&sigset);
|
||||
sigaddset(&sigset, SIGCHLD);
|
||||
|
||||
|
||||
auto get_timespec =
|
||||
[](const Duration & dur)
|
||||
{
|
||||
::timespec ts;
|
||||
ts.tv_sec = std::chrono::duration_cast<std::chrono::seconds>(dur).count();
|
||||
ts.tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(dur).count() % 1000000000;
|
||||
return ts;
|
||||
};
|
||||
|
||||
|
||||
bool timed_out = false;
|
||||
int ret;
|
||||
|
||||
struct ::sigaction old_sig;
|
||||
if (-1 == ::sigaction(SIGCHLD, nullptr, &old_sig))
|
||||
{
|
||||
ec = get_last_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(BOOST_POSIX_HAS_SIGTIMEDWAIT)
|
||||
do
|
||||
{
|
||||
auto ts = get_timespec(time_out - Clock::now());
|
||||
ret = ::sigtimedwait(&sigset, nullptr, &ts);
|
||||
errno = 0;
|
||||
if ((ret == SIGCHLD) && (old_sig.sa_handler != SIG_DFL) && (old_sig.sa_handler != SIG_IGN))
|
||||
old_sig.sa_handler(ret);
|
||||
|
||||
ret = ::waitpid(-p.grp, &siginfo.si_status, 0); //so in case it exited, we wanna reap it first
|
||||
if (ret == -1)
|
||||
{
|
||||
ec = get_last_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
//check if we're done
|
||||
ret = ::waitid(P_PGID, p.grp, &siginfo, WEXITED | WNOHANG);
|
||||
|
||||
}
|
||||
while (((ret != -1) || (errno != ECHILD)) && !(timed_out = (Clock::now() > time_out)));
|
||||
#else
|
||||
//if we do not have sigtimedwait, we fork off a child process to get the signal in time
|
||||
pid_t timeout_pid = ::fork();
|
||||
if (timeout_pid == -1)
|
||||
{
|
||||
ec = boost::process::detail::get_last_error();
|
||||
return true;
|
||||
}
|
||||
else if (timeout_pid == 0)
|
||||
{
|
||||
auto ts = get_timespec(time_out - Clock::now());
|
||||
::setpgid(0, p.grp);
|
||||
::nanosleep(&ts, nullptr);
|
||||
::exit(0);
|
||||
}
|
||||
|
||||
struct child_cleaner_t
|
||||
{
|
||||
pid_t pid;
|
||||
~child_cleaner_t()
|
||||
{
|
||||
int res;
|
||||
::kill(pid, -15);
|
||||
::waitpid(pid, &res, WNOHANG);
|
||||
}
|
||||
};
|
||||
child_cleaner_t child_cleaner{timeout_pid};
|
||||
bool timed_out;
|
||||
|
||||
do
|
||||
{
|
||||
int ret_sig = 0;
|
||||
int status;
|
||||
if ((::waitpid(timeout_pid, &status, WNOHANG) != 0)
|
||||
&& (WIFEXITED(status) || WIFSIGNALED(status)))
|
||||
ret = ::sigwait(&sigset, nullptr);
|
||||
errno = 0;
|
||||
if ((ret == SIGCHLD) && (old_sig.sa_handler != SIG_DFL) && (old_sig.sa_handler != SIG_IGN))
|
||||
old_sig.sa_handler(ret);
|
||||
|
||||
ret = ::waitpid(-p.grp, &siginfo.si_status, 0); //so in case it exited, we wanna reap it first
|
||||
if (ret == -1)
|
||||
ret = ::waitpid(-p.grp, &status, WNOHANG);
|
||||
if (ret == 0)
|
||||
{
|
||||
ec = get_last_error();
|
||||
return false;
|
||||
timed_out = Clock::now() >= time_out;
|
||||
if (timed_out)
|
||||
return false;
|
||||
}
|
||||
|
||||
//check if we're done
|
||||
ret = ::waitid(P_PGID, p.grp, &siginfo, WEXITED | WNOHANG);
|
||||
|
||||
}
|
||||
while (((ret != -1) || (errno != ECHILD)) && !(timed_out = (Clock::now() > time_out)));
|
||||
while ((ret == 0) ||
|
||||
(((ret == -1) && errno == EINTR) ||
|
||||
((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))));
|
||||
|
||||
#endif
|
||||
|
||||
if (errno != ECHILD)
|
||||
{
|
||||
if (ret == -1)
|
||||
ec = boost::process::detail::get_last_error();
|
||||
return !timed_out;
|
||||
}
|
||||
else
|
||||
{
|
||||
ec.clear();
|
||||
return true; //even if timed out, there are no child proccessess left
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template< class Clock, class Duration >
|
||||
|
||||
@@ -21,9 +21,6 @@ class basic_streambuf;
|
||||
typedef basic_streambuf<std::allocator<char>> streambuf;
|
||||
class io_context;
|
||||
|
||||
class executor;
|
||||
|
||||
|
||||
template <typename Handler>
|
||||
class basic_yield_context;
|
||||
|
||||
@@ -37,10 +34,7 @@ class basic_stream_handle;
|
||||
|
||||
typedef basic_stream_handle<stream_handle_service> stream_handle;
|
||||
#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
|
||||
template <typename Executor>
|
||||
class basic_stream_handle;
|
||||
typedef basic_stream_handle<executor> stream_handle;
|
||||
|
||||
class stream_handle;
|
||||
#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
|
||||
|
||||
|
||||
@@ -52,9 +46,7 @@ class basic_object_handle;
|
||||
|
||||
typedef basic_object_handle<object_handle_service> object_handle;
|
||||
#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
|
||||
template <typename Executor>
|
||||
class basic_object_handle;
|
||||
typedef basic_object_handle<executor> object_handle;
|
||||
class object_handle;
|
||||
#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
|
||||
|
||||
} //windows
|
||||
|
||||
@@ -48,28 +48,28 @@ struct async_in_buffer : ::boost::process::detail::windows::handler_base_ext,
|
||||
template <typename Executor>
|
||||
inline void on_success(Executor&)
|
||||
{
|
||||
auto pipe_ = this->pipe;
|
||||
auto pipe = this->pipe;
|
||||
|
||||
if (this->promise)
|
||||
{
|
||||
auto promise_ = this->promise;
|
||||
auto promise = this->promise;
|
||||
|
||||
boost::asio::async_write(*pipe_, buf,
|
||||
[promise_](const boost::system::error_code & ec, std::size_t)
|
||||
boost::asio::async_write(*pipe, buf,
|
||||
[promise](const boost::system::error_code & ec, std::size_t)
|
||||
{
|
||||
if (ec && (ec.value() != ::boost::winapi::ERROR_BROKEN_PIPE_))
|
||||
{
|
||||
std::error_code e(ec.value(), std::system_category());
|
||||
promise_->set_exception(std::make_exception_ptr(process_error(e)));
|
||||
promise->set_exception(std::make_exception_ptr(process_error(e)));
|
||||
}
|
||||
promise_->set_value();
|
||||
promise->set_value();
|
||||
});
|
||||
}
|
||||
else
|
||||
boost::asio::async_write(*pipe_, buf,
|
||||
[pipe_](const boost::system::error_code&, std::size_t){});
|
||||
boost::asio::async_write(*pipe, buf,
|
||||
[pipe](const boost::system::error_code&, std::size_t){});
|
||||
|
||||
std::move(*pipe_).source().close();
|
||||
std::move(*pipe).source().close();
|
||||
|
||||
|
||||
this->pipe = nullptr;
|
||||
|
||||
@@ -80,10 +80,10 @@ struct async_out_buffer : ::boost::process::detail::windows::handler_base_ext,
|
||||
template <typename Executor>
|
||||
inline void on_success(Executor&)
|
||||
{
|
||||
auto pipe_ = this->pipe;
|
||||
boost::asio::async_read(*pipe_, buf,
|
||||
[pipe_](const boost::system::error_code&, std::size_t){});
|
||||
std::move(*pipe_).sink().close();
|
||||
auto pipe = this->pipe;
|
||||
boost::asio::async_read(*pipe, buf,
|
||||
[pipe](const boost::system::error_code&, std::size_t){});
|
||||
std::move(*pipe).sink().close();
|
||||
this->pipe = nullptr;
|
||||
|
||||
}
|
||||
@@ -122,34 +122,34 @@ struct async_out_future : ::boost::process::detail::windows::handler_base_ext,
|
||||
template <typename Executor>
|
||||
inline void on_success(Executor&)
|
||||
{
|
||||
auto pipe_ = this->pipe;
|
||||
auto buffer_ = this->buffer;
|
||||
auto promise_ = this->promise;
|
||||
std::move(*pipe_).sink().close();
|
||||
boost::asio::async_read(*pipe_, *buffer_,
|
||||
[pipe_, buffer_, promise_](const boost::system::error_code& ec, std::size_t)
|
||||
auto pipe = this->pipe;
|
||||
auto buffer = this->buffer;
|
||||
auto promise = this->promise;
|
||||
std::move(*pipe).sink().close();
|
||||
boost::asio::async_read(*pipe, *buffer,
|
||||
[pipe, buffer, promise](const boost::system::error_code& ec, std::size_t)
|
||||
{
|
||||
if (ec && (ec.value() != ::boost::winapi::ERROR_BROKEN_PIPE_))
|
||||
{
|
||||
std::error_code e(ec.value(), std::system_category());
|
||||
promise_->set_exception(std::make_exception_ptr(process_error(e)));
|
||||
promise->set_exception(std::make_exception_ptr(process_error(e)));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::istream is (buffer_.get());
|
||||
std::istream is (buffer.get());
|
||||
Type arg;
|
||||
if (buffer_->size() > 0)
|
||||
if (buffer->size() > 0)
|
||||
{
|
||||
arg.resize(buffer_->size());
|
||||
is.read(&*arg.begin(), buffer_->size());
|
||||
arg.resize(buffer->size());
|
||||
is.read(&*arg.begin(), buffer->size());
|
||||
}
|
||||
|
||||
promise_->set_value(std::move(arg));
|
||||
promise->set_value(std::move(arg));
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
this->pipe = nullptr;
|
||||
this->pipe = nullptr;
|
||||
this->buffer = nullptr;
|
||||
this->promise = nullptr;
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <boost/winapi/access_rights.hpp>
|
||||
#include <boost/winapi/process.hpp>
|
||||
#include <boost/process/detail/windows/basic_pipe.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/windows/stream_handle.hpp>
|
||||
#include <atomic>
|
||||
#include <system_error>
|
||||
@@ -100,12 +99,12 @@ public:
|
||||
if (_sink.is_open())
|
||||
{
|
||||
_sink.close();
|
||||
_sink = handle_type(_sink.get_executor());
|
||||
_sink = handle_type(_sink.get_io_context());
|
||||
}
|
||||
if (_source.is_open())
|
||||
{
|
||||
_source.close();
|
||||
_source = handle_type(_source.get_executor());
|
||||
_source = handle_type(_source.get_io_context());
|
||||
}
|
||||
}
|
||||
void close(boost::system::error_code & ec)
|
||||
@@ -113,12 +112,12 @@ public:
|
||||
if (_sink.is_open())
|
||||
{
|
||||
_sink.close(ec);
|
||||
_sink = handle_type(_sink.get_executor());
|
||||
_sink = handle_type(_sink.get_io_context());
|
||||
}
|
||||
if (_source.is_open())
|
||||
{
|
||||
_source.close(ec);
|
||||
_source = handle_type(_source.get_executor());
|
||||
_source = handle_type(_source.get_io_context());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,9 +128,9 @@ public:
|
||||
void async_close()
|
||||
{
|
||||
if (_sink.is_open())
|
||||
boost::asio::post(_sink.get_executor(), [this]{_sink.close();});
|
||||
_sink.get_io_context(). post([this]{_sink.close();});
|
||||
if (_source.is_open())
|
||||
boost::asio::post(_source.get_executor(), [this]{_source.close();});
|
||||
_source.get_io_context().post([this]{_source.close();});
|
||||
}
|
||||
|
||||
template<typename MutableBufferSequence>
|
||||
@@ -145,18 +144,6 @@ public:
|
||||
return _sink.write_some(buffers);
|
||||
}
|
||||
|
||||
|
||||
template<typename MutableBufferSequence>
|
||||
std::size_t read_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept
|
||||
{
|
||||
return _source.read_some(buffers, ec);
|
||||
}
|
||||
template<typename MutableBufferSequence>
|
||||
std::size_t write_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept
|
||||
{
|
||||
return _sink.write_some(buffers, ec);
|
||||
}
|
||||
|
||||
native_handle_type native_source() const {return const_cast<boost::asio::windows::stream_handle&>(_source).native_handle();}
|
||||
native_handle_type native_sink () const {return const_cast<boost::asio::windows::stream_handle&>(_sink ).native_handle();}
|
||||
|
||||
@@ -168,7 +155,7 @@ public:
|
||||
const MutableBufferSequence & buffers,
|
||||
ReadHandler &&handler)
|
||||
{
|
||||
return _source.async_read_some(buffers, std::forward<ReadHandler>(handler));
|
||||
_source.async_read_some(buffers, std::forward<ReadHandler>(handler));
|
||||
}
|
||||
|
||||
template<typename ConstBufferSequence,
|
||||
@@ -179,7 +166,7 @@ public:
|
||||
const ConstBufferSequence & buffers,
|
||||
WriteHandler && handler)
|
||||
{
|
||||
return _sink.async_write_some(buffers, std::forward<WriteHandler>(handler));
|
||||
_sink.async_write_some(buffers, std::forward<WriteHandler>(handler));
|
||||
}
|
||||
|
||||
const handle_type & sink () const & {return _sink;}
|
||||
@@ -190,13 +177,13 @@ public:
|
||||
|
||||
handle_type source(::boost::asio::io_context& ios) &&
|
||||
{
|
||||
::boost::asio::windows::stream_handle stolen(ios.get_executor(), _source.native_handle());
|
||||
::boost::asio::windows::stream_handle stolen(ios, _source.native_handle());
|
||||
_source.assign(::boost::winapi::INVALID_HANDLE_VALUE_);
|
||||
return stolen;
|
||||
}
|
||||
handle_type sink (::boost::asio::io_context& ios) &&
|
||||
{
|
||||
::boost::asio::windows::stream_handle stolen(ios.get_executor(), _sink.native_handle());
|
||||
::boost::asio::windows::stream_handle stolen(ios, _sink.native_handle());
|
||||
_sink.assign(::boost::winapi::INVALID_HANDLE_VALUE_);
|
||||
return stolen;
|
||||
}
|
||||
@@ -215,7 +202,7 @@ public:
|
||||
::boost::winapi::DUPLICATE_SAME_ACCESS_))
|
||||
throw_last_error("Duplicate Pipe Failed");
|
||||
|
||||
return ::boost::asio::windows::stream_handle(ios.get_executor(), source);
|
||||
return ::boost::asio::windows::stream_handle(ios, source);
|
||||
}
|
||||
handle_type sink (::boost::asio::io_context& ios) const &
|
||||
{
|
||||
@@ -231,15 +218,15 @@ public:
|
||||
::boost::winapi::DUPLICATE_SAME_ACCESS_))
|
||||
throw_last_error("Duplicate Pipe Failed");
|
||||
|
||||
return ::boost::asio::windows::stream_handle(ios.get_executor(), sink);
|
||||
return ::boost::asio::windows::stream_handle(ios, sink);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
async_pipe::async_pipe(const async_pipe& p) :
|
||||
_source(const_cast<handle_type&>(p._source).get_executor()),
|
||||
_sink (const_cast<handle_type&>(p._sink).get_executor())
|
||||
_source(const_cast<handle_type&>(p._source).get_io_context()),
|
||||
_sink (const_cast<handle_type&>(p._sink).get_io_context())
|
||||
{
|
||||
auto proc = ::boost::winapi::GetCurrentProcess();
|
||||
|
||||
@@ -338,8 +325,8 @@ async_pipe& async_pipe::operator=(const async_pipe & p)
|
||||
throw_last_error("Duplicate Pipe Failed");
|
||||
|
||||
//so we also assign the io_context
|
||||
_source = ::boost::asio::windows::stream_handle(source_in.get_executor(), source);
|
||||
_sink = ::boost::asio::windows::stream_handle(source_in.get_executor(), sink);
|
||||
_source = ::boost::asio::windows::stream_handle(source_in.get_io_context(), source);
|
||||
_sink = ::boost::asio::windows::stream_handle(source_in.get_io_context(), sink);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -143,13 +143,8 @@ basic_pipe<Char, Traits>::basic_pipe(const std::string & name)
|
||||
static constexpr int FILE_FLAG_OVERLAPPED_ = 0x40000000; //temporary
|
||||
//static constexpr int FILE_ATTRIBUTE_NORMAL_ = 0x00000080; //temporary
|
||||
|
||||
#if BOOST_NO_ANSI_APIS
|
||||
std::wstring name_ = boost::process::detail::convert(name);
|
||||
#else
|
||||
auto &name_ = name;
|
||||
#endif
|
||||
::boost::winapi::HANDLE_ source = ::boost::winapi::create_named_pipe(
|
||||
name_.c_str(),
|
||||
name.c_str(),
|
||||
::boost::winapi::PIPE_ACCESS_INBOUND_
|
||||
| FILE_FLAG_OVERLAPPED_, //write flag
|
||||
0, 1, 8192, 8192, 0, nullptr);
|
||||
|
||||
@@ -84,7 +84,7 @@ struct startup_info_impl
|
||||
void set_startup_info_ex()
|
||||
{
|
||||
startup_info.cb = sizeof(startup_info_ex_t);
|
||||
creation_flags |= ::boost::winapi::EXTENDED_STARTUPINFO_PRESENT_;
|
||||
creation_flags = ::boost::winapi::EXTENDED_STARTUPINFO_PRESENT_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -84,37 +84,22 @@ inline void enable_break_away(::boost::winapi::HANDLE_ h, std::error_code & ec)
|
||||
ec = get_last_error();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
inline void associate_completion_port(::boost::winapi::HANDLE_ job,
|
||||
::boost::winapi::HANDLE_ io_port)
|
||||
{
|
||||
workaround::JOBOBJECT_ASSOCIATE_COMPLETION_PORT_ port;
|
||||
port.CompletionKey = job;
|
||||
port.CompletionPort = io_port;
|
||||
|
||||
if (!workaround::set_information_job_object(
|
||||
job,
|
||||
workaround::JobObjectAssociateCompletionPortInformation_,
|
||||
static_cast<void*>(&port),
|
||||
sizeof(port)))
|
||||
throw_last_error("SetInformationJobObject() failed");
|
||||
}
|
||||
|
||||
struct group_handle
|
||||
{
|
||||
::boost::winapi::HANDLE_ _job_object;
|
||||
::boost::winapi::HANDLE_ _io_port;
|
||||
|
||||
typedef ::boost::winapi::HANDLE_ handle_t;
|
||||
handle_t handle() const { return _job_object; }
|
||||
|
||||
explicit group_handle(handle_t h) :
|
||||
_job_object(h),
|
||||
_io_port(::CreateIoCompletionPort(::boost::winapi::INVALID_HANDLE_VALUE_, nullptr, 0, 1))
|
||||
_job_object(h)
|
||||
{
|
||||
enable_break_away(_job_object);
|
||||
associate_completion_port(_job_object, _io_port);
|
||||
}
|
||||
|
||||
|
||||
@@ -125,21 +110,15 @@ struct group_handle
|
||||
~group_handle()
|
||||
{
|
||||
::boost::winapi::CloseHandle(_job_object);
|
||||
::boost::winapi::CloseHandle(_io_port);
|
||||
}
|
||||
group_handle(const group_handle & c) = delete;
|
||||
group_handle(group_handle && c) : _job_object(c._job_object),
|
||||
_io_port(c._io_port)
|
||||
group_handle(group_handle && c) : _job_object(c._job_object)
|
||||
{
|
||||
c._job_object = ::boost::winapi::invalid_handle_value;
|
||||
c._io_port = ::boost::winapi::invalid_handle_value;
|
||||
}
|
||||
group_handle &operator=(const group_handle & c) = delete;
|
||||
group_handle &operator=(group_handle && c)
|
||||
{
|
||||
::boost::winapi::CloseHandle(_io_port);
|
||||
_io_port = c._io_port;
|
||||
c._io_port = ::boost::winapi::invalid_handle_value;
|
||||
|
||||
::boost::winapi::CloseHandle(_job_object);
|
||||
_job_object = c._job_object;
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_PROCESS_WINDOWS_IO_CONTEXT_REF_HPP_
|
||||
#define BOOST_PROCESS_WINDOWS_IO_CONTEXT_REF_HPP_
|
||||
#ifndef BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_
|
||||
#define BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_
|
||||
|
||||
#include <boost/process/detail/handler_base.hpp>
|
||||
#include <boost/process/detail/windows/async_handler.hpp>
|
||||
@@ -130,7 +130,7 @@ struct io_context_ref : boost::process::detail::handler_base
|
||||
boost::asio::io_context & ios, void * handle,
|
||||
const std::shared_ptr<std::atomic<int>> &exit_status)
|
||||
: funcs(std::move(funcs)),
|
||||
handle(new boost::asio::windows::object_handle(ios.get_executor(), handle)),
|
||||
handle(new boost::asio::windows::object_handle(ios, handle)),
|
||||
exit_status(exit_status)
|
||||
{
|
||||
|
||||
@@ -157,4 +157,4 @@ private:
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /* BOOST_PROCESS_WINDOWS_IO_CONTEXT_REF_HPP_ */
|
||||
#endif /* BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_ */
|
||||
|
||||
@@ -9,184 +9,68 @@
|
||||
#include <boost/winapi/config.hpp>
|
||||
#include <boost/winapi/basic_types.hpp>
|
||||
#include <boost/winapi/dll.hpp>
|
||||
#include <boost/winapi/overlapped.hpp>
|
||||
|
||||
#if defined( BOOST_USE_WINDOWS_H )
|
||||
#include <windows.h>
|
||||
#else
|
||||
extern "C"
|
||||
{
|
||||
BOOST_SYMBOL_IMPORT ::boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC CreateIoCompletionPort(
|
||||
::boost::winapi::HANDLE_ FileHandle,
|
||||
::boost::winapi::HANDLE_ ExistingCompletionPort,
|
||||
::boost::winapi::ULONG_PTR_ CompletionKey,
|
||||
::boost::winapi::DWORD_ NumberOfConcurrentThreads
|
||||
);
|
||||
|
||||
BOOST_SYMBOL_IMPORT ::boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC GetQueuedCompletionStatus(
|
||||
::boost::winapi::HANDLE_ CompletionPort,
|
||||
::boost::winapi::LPDWORD_ lpNumberOfBytes,
|
||||
::boost::winapi::ULONG_PTR_ *lpCompletionKey,
|
||||
_OVERLAPPED **lpOverlapped,
|
||||
::boost::winapi::DWORD_ dwMilliseconds
|
||||
);
|
||||
|
||||
}
|
||||
#endif
|
||||
namespace boost { namespace process { namespace detail { namespace windows { namespace workaround {
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
struct JOBOBJECT_ASSOCIATE_COMPLETION_PORT_
|
||||
{
|
||||
::boost::winapi::PVOID_ CompletionKey;
|
||||
::boost::winapi::HANDLE_ CompletionPort;
|
||||
};
|
||||
|
||||
constexpr static int JOB_OBJECT_MSG_END_OF_JOB_TIME_ = 1;
|
||||
constexpr static int JOB_OBJECT_MSG_END_OF_PROCESS_TIME_ = 2;
|
||||
constexpr static int JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT_ = 3;
|
||||
constexpr static int JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO_ = 4;
|
||||
constexpr static int JOB_OBJECT_MSG_NEW_PROCESS_ = 6;
|
||||
constexpr static int JOB_OBJECT_MSG_EXIT_PROCESS_ = 7;
|
||||
constexpr static int JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS_ = 8;
|
||||
constexpr static int JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT_ = 9;
|
||||
constexpr static int JOB_OBJECT_MSG_JOB_MEMORY_LIMIT_ = 10;
|
||||
constexpr static int JOB_OBJECT_MSG_NOTIFICATION_LIMIT_ = 11;
|
||||
constexpr static int JOB_OBJECT_MSG_JOB_CYCLE_TIME_LIMIT_ = 12;
|
||||
constexpr static int JOB_OBJECT_MSG_SILO_TERMINATED_ = 13;
|
||||
|
||||
}
|
||||
|
||||
BOOST_FORCEINLINE ::boost::winapi::BOOL_ get_queued_completion_status(
|
||||
::boost::winapi::HANDLE_ CompletionPort,
|
||||
::boost::winapi::LPDWORD_ lpNumberOfBytes,
|
||||
::boost::winapi::ULONG_PTR_ *lpCompletionKey,
|
||||
::boost::winapi::LPOVERLAPPED_ *lpOverlapped,
|
||||
::boost::winapi::DWORD_ dwMilliseconds)
|
||||
{
|
||||
return ::GetQueuedCompletionStatus(
|
||||
CompletionPort,
|
||||
lpNumberOfBytes,
|
||||
lpCompletionKey,
|
||||
reinterpret_cast<::_OVERLAPPED**>(lpOverlapped),
|
||||
dwMilliseconds);
|
||||
}
|
||||
|
||||
#if defined( BOOST_USE_WINDOWS_H )
|
||||
|
||||
constexpr auto static JobObjectExtendedLimitInformation_ = ::JobObjectExtendedLimitInformation;
|
||||
constexpr auto static JobObjectAssociateCompletionPortInformation_ = ::JobObjectAssociateCompletionPortInformation;
|
||||
constexpr auto static JobObjectBasicAccountingInformation_ = ::JobObjectBasicAccountingInformation;
|
||||
|
||||
using JOBOBJECT_BASIC_LIMIT_INFORMATION_ = ::JOBOBJECT_BASIC_LIMIT_INFORMATION;
|
||||
using JOBOBJECTINFOCLASS_ = ::JOBOBJECTINFOCLASS;
|
||||
using IO_COUNTERS_ = ::IO_COUNTERS;
|
||||
using JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ = ::JOBOBJECT_EXTENDED_LIMIT_INFORMATION;
|
||||
using JOBOBJECT_BASIC_ACCOUNTING_INFORMATION_ = ::JOBOBJECT_BASIC_ACCOUNTING_INFORMATION;
|
||||
|
||||
inline ::boost::winapi::BOOL_ query_information_job_object(
|
||||
::boost::winapi::HANDLE_ hJob,
|
||||
JOBOBJECTINFOCLASS_ JobObjectInfoClass,
|
||||
void * lpJobObjectInfo,
|
||||
::boost::winapi::DWORD_ cbJobObjectInfoLength,
|
||||
::boost::winapi::DWORD_ *lpReturnLength)
|
||||
{
|
||||
return ::QueryInformationJobObject(hJob, JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength, lpReturnLength);
|
||||
}
|
||||
|
||||
inline ::boost::winapi::BOOL_ set_information_job_object(
|
||||
::boost::winapi::HANDLE_ hJob,
|
||||
JOBOBJECTINFOCLASS_ JobObjectInfoClass,
|
||||
void * lpJobObjectInfo,
|
||||
::boost::winapi::DWORD_ cbJobObjectInfoLength)
|
||||
{
|
||||
return ::SetInformationJobObject(hJob, JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
//this import workaround is to keep it a header-only library. and enums cannot be imported from the winapi.
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
typedef enum _JOBOBJECTINFOCLASS_
|
||||
{
|
||||
JobObjectBasicAccountingInformation_ = 1,
|
||||
JobObjectBasicLimitInformation_,
|
||||
JobObjectBasicProcessIdList_,
|
||||
JobObjectBasicUIRestrictions_,
|
||||
JobObjectSecurityLimitInformation_,
|
||||
JobObjectEndOfJobTimeInformation_,
|
||||
JobObjectAssociateCompletionPortInformation_,
|
||||
JobObjectBasicAndIoAccountingInformation_,
|
||||
JobObjectExtendedLimitInformation_,
|
||||
JobObjectJobSetInformation_,
|
||||
JobObjectGroupInformation_,
|
||||
JobObjectNotificationLimitInformation_,
|
||||
JobObjectLimitViolationInformation_,
|
||||
JobObjectGroupInformationEx_,
|
||||
JobObjectCpuRateControlInformation_,
|
||||
JobObjectCompletionFilter_,
|
||||
JobObjectCompletionCounter_,
|
||||
JobObjectReserved1Information_ = 18,
|
||||
JobObjectReserved2Information_,
|
||||
JobObjectReserved3Information_,
|
||||
JobObjectReserved4Information_,
|
||||
JobObjectReserved5Information_,
|
||||
JobObjectReserved6Information_,
|
||||
JobObjectReserved7Information_,
|
||||
JobObjectReserved8Information_,
|
||||
MaxJobObjectInfoClass_
|
||||
} JOBOBJECTINFOCLASS_;
|
||||
typedef enum _JOBOBJECTINFOCLASS_ {
|
||||
JobObjectBasicAccountingInformation_ = 1, JobObjectBasicLimitInformation_,
|
||||
JobObjectBasicProcessIdList_, JobObjectBasicUIRestrictions_,
|
||||
JobObjectSecurityLimitInformation_, JobObjectEndOfJobTimeInformation_,
|
||||
JobObjectAssociateCompletionPortInformation_, JobObjectBasicAndIoAccountingInformation_,
|
||||
JobObjectExtendedLimitInformation_, JobObjectJobSetInformation_,
|
||||
JobObjectGroupInformation_,
|
||||
JobObjectNotificationLimitInformation_,
|
||||
JobObjectLimitViolationInformation_,
|
||||
JobObjectGroupInformationEx_,
|
||||
JobObjectCpuRateControlInformation_,
|
||||
JobObjectCompletionFilter_,
|
||||
JobObjectCompletionCounter_,
|
||||
JobObjectReserved1Information_ = 18,
|
||||
JobObjectReserved2Information_,
|
||||
JobObjectReserved3Information_,
|
||||
JobObjectReserved4Information_,
|
||||
JobObjectReserved5Information_,
|
||||
JobObjectReserved6Information_,
|
||||
JobObjectReserved7Information_,
|
||||
JobObjectReserved8Information_,
|
||||
MaxJobObjectInfoClass_
|
||||
} JOBOBJECTINFOCLASS_;
|
||||
|
||||
typedef struct _JOBOBJECT_BASIC_LIMIT_INFORMATION_
|
||||
{
|
||||
::boost::winapi::LARGE_INTEGER_ PerProcessUserTimeLimit;
|
||||
::boost::winapi::LARGE_INTEGER_ PerJobUserTimeLimit;
|
||||
::boost::winapi::DWORD_ LimitFlags;
|
||||
::boost::winapi::SIZE_T_ MinimumWorkingSetSize;
|
||||
::boost::winapi::SIZE_T_ MaximumWorkingSetSize;
|
||||
::boost::winapi::DWORD_ ActiveProcessLimit;
|
||||
::boost::winapi::ULONG_PTR_ Affinity;
|
||||
::boost::winapi::DWORD_ PriorityClass;
|
||||
::boost::winapi::DWORD_ SchedulingClass;
|
||||
typedef struct _JOBOBJECT_BASIC_LIMIT_INFORMATION_ {
|
||||
::boost::winapi::LARGE_INTEGER_ PerProcessUserTimeLimit;
|
||||
::boost::winapi::LARGE_INTEGER_ PerJobUserTimeLimit;
|
||||
::boost::winapi::DWORD_ LimitFlags;
|
||||
::boost::winapi::SIZE_T_ MinimumWorkingSetSize;
|
||||
::boost::winapi::SIZE_T_ MaximumWorkingSetSize;
|
||||
::boost::winapi::DWORD_ ActiveProcessLimit;
|
||||
::boost::winapi::ULONG_PTR_ Affinity;
|
||||
::boost::winapi::DWORD_ PriorityClass;
|
||||
::boost::winapi::DWORD_ SchedulingClass;
|
||||
} JOBOBJECT_BASIC_LIMIT_INFORMATION_;
|
||||
|
||||
|
||||
typedef struct _JOBOBJECT_BASIC_ACCOUNTING_INFORMATION_ {
|
||||
::boost::winapi::LARGE_INTEGER_ TotalUserTime;
|
||||
::boost::winapi::LARGE_INTEGER_ TotalKernelTime;
|
||||
::boost::winapi::LARGE_INTEGER_ ThisPeriodTotalUserTime;
|
||||
::boost::winapi::LARGE_INTEGER_ ThisPeriodTotalKernelTime;
|
||||
::boost::winapi::DWORD_ TotalPageFaultCount;
|
||||
::boost::winapi::DWORD_ TotalProcesses;
|
||||
::boost::winapi::DWORD_ ActiveProcesses;
|
||||
::boost::winapi::DWORD_ TotalTerminatedProcesses;
|
||||
} JOBOBJECT_BASIC_ACCOUNTING_INFORMATION_;
|
||||
|
||||
typedef struct _IO_COUNTERS_
|
||||
{
|
||||
::boost::winapi::ULONGLONG_ ReadOperationCount;
|
||||
::boost::winapi::ULONGLONG_ WriteOperationCount;
|
||||
::boost::winapi::ULONGLONG_ OtherOperationCount;
|
||||
::boost::winapi::ULONGLONG_ ReadTransferCount;
|
||||
::boost::winapi::ULONGLONG_ WriteTransferCount;
|
||||
::boost::winapi::ULONGLONG_ OtherTransferCount;
|
||||
typedef struct _IO_COUNTERS_ {
|
||||
::boost::winapi::ULONGLONG_ ReadOperationCount;
|
||||
::boost::winapi::ULONGLONG_ WriteOperationCount;
|
||||
::boost::winapi::ULONGLONG_ OtherOperationCount;
|
||||
::boost::winapi::ULONGLONG_ ReadTransferCount;
|
||||
::boost::winapi::ULONGLONG_ WriteTransferCount;
|
||||
::boost::winapi::ULONGLONG_ OtherTransferCount;
|
||||
} IO_COUNTERS_;
|
||||
|
||||
|
||||
typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION_
|
||||
{
|
||||
JOBOBJECT_BASIC_LIMIT_INFORMATION_ BasicLimitInformation;
|
||||
IO_COUNTERS_ IoInfo;
|
||||
::boost::winapi::SIZE_T_ ProcessMemoryLimit;
|
||||
::boost::winapi::SIZE_T_ JobMemoryLimit;
|
||||
::boost::winapi::SIZE_T_ PeakProcessMemoryUsed;
|
||||
::boost::winapi::SIZE_T_ PeakJobMemoryUsed;
|
||||
typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ {
|
||||
JOBOBJECT_BASIC_LIMIT_INFORMATION_ BasicLimitInformation;
|
||||
IO_COUNTERS_ IoInfo;
|
||||
::boost::winapi::SIZE_T_ ProcessMemoryLimit;
|
||||
::boost::winapi::SIZE_T_ JobMemoryLimit;
|
||||
::boost::winapi::SIZE_T_ PeakProcessMemoryUsed;
|
||||
::boost::winapi::SIZE_T_ PeakJobMemoryUsed;
|
||||
} JOBOBJECT_EXTENDED_LIMIT_INFORMATION_;
|
||||
|
||||
|
||||
@@ -198,7 +82,7 @@ typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION_
|
||||
_Out_opt_ LPDWORD lpReturnLength
|
||||
);
|
||||
*/
|
||||
typedef ::boost::winapi::BOOL_ (BOOST_WINAPI_WINAPI_CC *query_information_job_object_p)(
|
||||
typedef ::boost::winapi::BOOL_ ( WINAPI *query_information_job_object_p)(
|
||||
::boost::winapi::HANDLE_,
|
||||
JOBOBJECTINFOCLASS_,
|
||||
void *,
|
||||
@@ -206,20 +90,17 @@ typedef ::boost::winapi::BOOL_ (BOOST_WINAPI_WINAPI_CC *query_information_job_ob
|
||||
::boost::winapi::DWORD_ *);
|
||||
|
||||
|
||||
inline ::boost::winapi::BOOL_ query_information_job_object(
|
||||
inline ::boost::winapi::BOOL_ WINAPI query_information_job_object(
|
||||
::boost::winapi::HANDLE_ hJob,
|
||||
JOBOBJECTINFOCLASS_ JobObjectInfoClass,
|
||||
void *lpJobObjectInfo,
|
||||
void * lpJobObjectInfo,
|
||||
::boost::winapi::DWORD_ cbJobObjectInfoLength,
|
||||
::boost::winapi::DWORD_ *lpReturnLength)
|
||||
{
|
||||
static ::boost::winapi::HMODULE_ h = ::boost::winapi::get_module_handle(
|
||||
L"Kernel32.dll");
|
||||
static query_information_job_object_p f = reinterpret_cast<query_information_job_object_p>(::boost::winapi::get_proc_address(
|
||||
h, "QueryInformationJobObject"));
|
||||
static ::boost::winapi::HMODULE_ h = ::boost::winapi::get_module_handle(L"Kernel32.dll");
|
||||
static query_information_job_object_p f = reinterpret_cast<query_information_job_object_p>(::boost::winapi::get_proc_address(h, "QueryInformationJobObject"));
|
||||
|
||||
return (*f)(hJob, JobObjectInfoClass, lpJobObjectInfo,
|
||||
cbJobObjectInfoLength, lpReturnLength);
|
||||
return (*f)(hJob, JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength, lpReturnLength);
|
||||
}
|
||||
|
||||
/*BOOL WINAPI SetInformationJobObject(
|
||||
@@ -229,7 +110,7 @@ inline ::boost::winapi::BOOL_ query_information_job_object(
|
||||
_In_ DWORD cbJobObjectInfoLength
|
||||
);*/
|
||||
|
||||
typedef ::boost::winapi::BOOL_ (BOOST_WINAPI_WINAPI_CC *set_information_job_object_p)(
|
||||
typedef ::boost::winapi::BOOL_ ( WINAPI *set_information_job_object_p)(
|
||||
::boost::winapi::HANDLE_,
|
||||
JOBOBJECTINFOCLASS_,
|
||||
void *,
|
||||
@@ -237,25 +118,22 @@ typedef ::boost::winapi::BOOL_ (BOOST_WINAPI_WINAPI_CC *set_information_job_obje
|
||||
|
||||
}
|
||||
|
||||
inline ::boost::winapi::BOOL_ set_information_job_object(
|
||||
inline ::boost::winapi::BOOL_ WINAPI set_information_job_object(
|
||||
::boost::winapi::HANDLE_ hJob,
|
||||
JOBOBJECTINFOCLASS_ JobObjectInfoClass,
|
||||
void *lpJobObjectInfo,
|
||||
void * lpJobObjectInfo,
|
||||
::boost::winapi::DWORD_ cbJobObjectInfoLength)
|
||||
{
|
||||
static ::boost::winapi::HMODULE_ h = ::boost::winapi::get_module_handle(
|
||||
L"Kernel32.dll");
|
||||
static set_information_job_object_p f = reinterpret_cast<set_information_job_object_p>(::boost::winapi::get_proc_address(
|
||||
h, "SetInformationJobObject"));
|
||||
static ::boost::winapi::HMODULE_ h = ::boost::winapi::get_module_handle(L"Kernel32.dll");
|
||||
static set_information_job_object_p f = reinterpret_cast<set_information_job_object_p>(::boost::winapi::get_proc_address(h, "SetInformationJobObject"));
|
||||
|
||||
return (*f)(hJob, JobObjectInfoClass, lpJobObjectInfo,
|
||||
cbJobObjectInfoLength);
|
||||
return (*f)(hJob, JobObjectInfoClass, lpJobObjectInfo, cbJobObjectInfoLength);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
constexpr static ::boost::winapi::DWORD_ JOB_OBJECT_LIMIT_BREAKAWAY_OK_ = 0x00000800;
|
||||
|
||||
}}}}}
|
||||
|
||||
|
||||
|
||||
#endif /* BOOST_PROCESS_DETAIL_WINDOWS_JOB_WORKAROUND_HPP_ */
|
||||
|
||||
@@ -25,10 +25,10 @@ struct on_exit_ : boost::process::detail::windows::async_handler
|
||||
template<typename Executor>
|
||||
std::function<void(int, const std::error_code&)> on_exit_handler(Executor&)
|
||||
{
|
||||
auto handler_ = this->handler;
|
||||
return [handler_](int exit_code, const std::error_code & ec)
|
||||
auto handler = this->handler;
|
||||
return [handler](int exit_code, const std::error_code & ec)
|
||||
{
|
||||
handler_(static_cast<int>(exit_code), ec);
|
||||
handler(static_cast<int>(exit_code), ec);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -55,9 +55,9 @@ inline boost::filesystem::path search_path(
|
||||
for (auto & ext : extensions)
|
||||
boost::to_lower(ext);
|
||||
|
||||
for (const boost::filesystem::path & pp_ : path)
|
||||
for (const boost::filesystem::path & pp : path)
|
||||
{
|
||||
auto p = pp_ / filename;
|
||||
auto p = pp / filename;
|
||||
for (boost::filesystem::path ext : extensions)
|
||||
{
|
||||
boost::filesystem::path pp = p;
|
||||
|
||||
@@ -34,7 +34,7 @@ struct create_no_window_ : public ::boost::process::detail::handler_base
|
||||
template <class Executor>
|
||||
void on_setup(Executor &exec) const
|
||||
{
|
||||
exec.creation_flags |= ::boost::winapi::CREATE_NO_WINDOW_;
|
||||
exec.creation_flags |= ::boost::detail::winapi::CREATE_NO_WINDOW_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#define BOOST_PROCESS_DETAIL_WINDOWS_WAIT_GROUP_HPP_
|
||||
|
||||
#include <boost/process/detail/config.hpp>
|
||||
#include <boost/process/detail/windows/group_handle.hpp>
|
||||
#include <boost/winapi/jobs.hpp>
|
||||
#include <boost/winapi/wait.hpp>
|
||||
#include <chrono>
|
||||
@@ -16,61 +15,11 @@ namespace boost { namespace process { namespace detail { namespace windows {
|
||||
|
||||
struct group_handle;
|
||||
|
||||
|
||||
inline bool wait_impl(const group_handle & p, std::error_code & ec, std::chrono::system_clock::rep wait_time)
|
||||
{
|
||||
::boost::winapi::DWORD_ completion_code;
|
||||
::boost::winapi::ULONG_PTR_ completion_key;
|
||||
::boost::winapi::LPOVERLAPPED_ overlapped;
|
||||
|
||||
auto start_time = std::chrono::system_clock::now();
|
||||
|
||||
while (workaround::get_queued_completion_status(
|
||||
p._io_port, &completion_code,
|
||||
&completion_key, &overlapped, wait_time))
|
||||
{
|
||||
if (reinterpret_cast<::boost::winapi::HANDLE_>(completion_key) == p._job_object &&
|
||||
completion_code == workaround::JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO_)
|
||||
{
|
||||
|
||||
//double check, could be a different handle from a child
|
||||
workaround::JOBOBJECT_BASIC_ACCOUNTING_INFORMATION_ info;
|
||||
if (!workaround::query_information_job_object(
|
||||
p._job_object,
|
||||
workaround::JobObjectBasicAccountingInformation_,
|
||||
static_cast<void *>(&info),
|
||||
sizeof(info), nullptr))
|
||||
{
|
||||
ec = get_last_error();
|
||||
return false;
|
||||
}
|
||||
else if (info.ActiveProcesses == 0)
|
||||
return false; //correct, nothing left.
|
||||
}
|
||||
//reduce the remaining wait time -> in case interrupted by something else
|
||||
if (wait_time != ::boost::winapi::infinite)
|
||||
{
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
|
||||
wait_time -= diff.count();
|
||||
start_time = now;
|
||||
if (wait_time <= 0)
|
||||
return true; //timeout with other source
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
auto ec_ = get_last_error();
|
||||
if (ec_.value() == ::boost::winapi::wait_timeout)
|
||||
return true; //timeout
|
||||
|
||||
ec = ec_;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void wait(const group_handle &p, std::error_code &ec)
|
||||
{
|
||||
wait_impl(p, ec, ::boost::winapi::infinite);
|
||||
if (::boost::winapi::WaitForSingleObject(p.handle(),
|
||||
::boost::winapi::infinite) == ::boost::winapi::wait_failed)
|
||||
ec = get_last_error();
|
||||
}
|
||||
|
||||
inline void wait(const group_handle &p)
|
||||
@@ -90,8 +39,16 @@ inline bool wait_until(
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
timeout_time - Clock::now());
|
||||
|
||||
auto timeout = wait_impl(p, ec, ms.count());
|
||||
return !ec && !timeout;
|
||||
::boost::winapi::DWORD_ wait_code;
|
||||
wait_code = ::boost::winapi::WaitForSingleObject(p.handle(), ms.count());
|
||||
|
||||
if (wait_code == ::boost::winapi::wait_failed)
|
||||
ec = get_last_error();
|
||||
|
||||
else if (wait_code == ::boost::winapi::wait_timeout)
|
||||
return false; //
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template< class Clock, class Duration >
|
||||
@@ -111,9 +68,7 @@ inline bool wait_for(
|
||||
const std::chrono::duration<Rep, Period>& rel_time,
|
||||
std::error_code &ec)
|
||||
{
|
||||
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(rel_time);
|
||||
auto timeout = wait_impl(p, ec, ms.count());
|
||||
return !ec && !timeout;
|
||||
return wait_until(p, std::chrono::steady_clock::now() + rel_time, ec);
|
||||
}
|
||||
|
||||
template< class Rep, class Period >
|
||||
|
||||
@@ -94,8 +94,8 @@ struct entry : const_entry<Char, Environment>
|
||||
explicit entry(string_type&& name, pointer data, environment_t & env) :
|
||||
father(std::move(name), data, env) {}
|
||||
|
||||
explicit entry(string_type &&name, environment_t & env_) :
|
||||
father(std::move(name), env_) {}
|
||||
explicit entry(string_type &&name, environment_t & env) :
|
||||
father(std::move(name), env) {}
|
||||
|
||||
entry(const entry&) = default;
|
||||
entry& operator=(const entry&) = default;
|
||||
|
||||
@@ -26,28 +26,10 @@ namespace boost {
|
||||
</programlisting>
|
||||
\endxmlonly
|
||||
*/
|
||||
namespace boost {
|
||||
namespace filesystem { class path; }
|
||||
|
||||
namespace process {
|
||||
|
||||
namespace detail {
|
||||
namespace boost { namespace process { namespace detail {
|
||||
|
||||
struct exe_
|
||||
{
|
||||
template<typename = void>
|
||||
inline exe_setter_<typename boost::filesystem::path::value_type> operator()(const boost::filesystem::path & pth) const
|
||||
{
|
||||
return exe_setter_<typename boost::filesystem::path::value_type>(pth.native());
|
||||
}
|
||||
|
||||
template<typename = void>
|
||||
inline exe_setter_<typename boost::filesystem::path::value_type> operator=(const boost::filesystem::path & pth) const
|
||||
{
|
||||
return exe_setter_<typename boost::filesystem::path::value_type>(pth.native());
|
||||
}
|
||||
|
||||
|
||||
template<typename Char>
|
||||
inline exe_setter_<Char> operator()(const Char *s) const
|
||||
{
|
||||
|
||||
@@ -164,10 +164,10 @@ struct require_io_context {};
|
||||
template<typename Executor>
|
||||
std::function<void(int, const std::error_code&)> on_exit_handler(Executor & exec)
|
||||
{
|
||||
auto handler_ = this->handler;
|
||||
return [handler_](int exit_code, const std::error_code & ec)
|
||||
auto handler = this->handler;
|
||||
return [handler](int exit_code, const std::error_code & ec)
|
||||
{
|
||||
handler_(static_cast<int>(exit_code), ec);
|
||||
handler(static_cast<int>(exit_code), ec);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ private:
|
||||
return false;
|
||||
|
||||
auto base = this->pbase();
|
||||
std::ptrdiff_t wrt = _pipe.write(base,
|
||||
auto wrt = _pipe.write(base,
|
||||
static_cast<typename pipe_type::int_type>(this->pptr() - base));
|
||||
std::ptrdiff_t diff = this->pptr() - base;
|
||||
|
||||
@@ -250,7 +250,7 @@ template<
|
||||
>
|
||||
class basic_ipstream : public std::basic_istream<CharT, Traits>
|
||||
{
|
||||
mutable basic_pipebuf<CharT, Traits> _buf;
|
||||
basic_pipebuf<CharT, Traits> _buf;
|
||||
public:
|
||||
|
||||
typedef basic_pipe<CharT, Traits> pipe_type;
|
||||
@@ -262,7 +262,7 @@ public:
|
||||
typedef typename Traits::off_type off_type ;
|
||||
|
||||
///Get access to the underlying stream_buf
|
||||
basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
|
||||
basic_pipebuf<CharT, Traits>* rdbuf() {return &_buf;};
|
||||
|
||||
///Default constructor.
|
||||
basic_ipstream() : std::basic_istream<CharT, Traits>(nullptr)
|
||||
@@ -272,10 +272,7 @@ public:
|
||||
///Copy constructor.
|
||||
basic_ipstream(const basic_ipstream & ) = delete;
|
||||
///Move constructor.
|
||||
basic_ipstream(basic_ipstream && lhs) : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf))
|
||||
{
|
||||
std::basic_istream<CharT, Traits>::rdbuf(&_buf);
|
||||
}
|
||||
basic_ipstream(basic_ipstream && ) = default;
|
||||
|
||||
///Move construct from a pipe.
|
||||
basic_ipstream(pipe_type && p) : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(p))
|
||||
@@ -292,12 +289,7 @@ public:
|
||||
///Copy assignment.
|
||||
basic_ipstream& operator=(const basic_ipstream & ) = delete;
|
||||
///Move assignment
|
||||
basic_ipstream& operator=(basic_ipstream && lhs)
|
||||
{
|
||||
std::basic_istream<CharT, Traits>::operator=(std::move(lhs));
|
||||
_buf = std::move(lhs);
|
||||
std::basic_istream<CharT, Traits>::rdbuf(&_buf);
|
||||
};
|
||||
basic_ipstream& operator=(basic_ipstream && ) = default;
|
||||
///Move assignment of a pipe.
|
||||
basic_ipstream& operator=(pipe_type && p)
|
||||
{
|
||||
@@ -334,7 +326,7 @@ template<
|
||||
>
|
||||
class basic_opstream : public std::basic_ostream<CharT, Traits>
|
||||
{
|
||||
mutable basic_pipebuf<CharT, Traits> _buf;
|
||||
basic_pipebuf<CharT, Traits> _buf;
|
||||
public:
|
||||
typedef basic_pipe<CharT, Traits> pipe_type;
|
||||
|
||||
@@ -346,7 +338,7 @@ public:
|
||||
|
||||
|
||||
///Get access to the underlying stream_buf
|
||||
basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
|
||||
basic_pipebuf<CharT, Traits>* rdbuf() const {return _buf;};
|
||||
|
||||
///Default constructor.
|
||||
basic_opstream() : std::basic_ostream<CharT, Traits>(nullptr)
|
||||
@@ -356,10 +348,8 @@ public:
|
||||
///Copy constructor.
|
||||
basic_opstream(const basic_opstream & ) = delete;
|
||||
///Move constructor.
|
||||
basic_opstream(basic_opstream && lhs) : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf))
|
||||
{
|
||||
std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
|
||||
}
|
||||
basic_opstream(basic_opstream && ) = default;
|
||||
|
||||
///Move construct from a pipe.
|
||||
basic_opstream(pipe_type && p) : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(p))
|
||||
{
|
||||
@@ -373,13 +363,7 @@ public:
|
||||
///Copy assignment.
|
||||
basic_opstream& operator=(const basic_opstream & ) = delete;
|
||||
///Move assignment
|
||||
basic_opstream& operator=(basic_opstream && lhs)
|
||||
{
|
||||
std::basic_ostream<CharT, Traits>::operator=(std::move(lhs));
|
||||
_buf = std::move(lhs);
|
||||
std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
|
||||
};
|
||||
|
||||
basic_opstream& operator=(basic_opstream && ) = default;
|
||||
///Move assignment of a pipe.
|
||||
basic_opstream& operator=(pipe_type && p)
|
||||
{
|
||||
@@ -417,7 +401,7 @@ template<
|
||||
>
|
||||
class basic_pstream : public std::basic_iostream<CharT, Traits>
|
||||
{
|
||||
mutable basic_pipebuf<CharT, Traits> _buf;
|
||||
basic_pipebuf<CharT, Traits> _buf;
|
||||
public:
|
||||
typedef basic_pipe<CharT, Traits> pipe_type;
|
||||
|
||||
@@ -429,7 +413,7 @@ public:
|
||||
|
||||
|
||||
///Get access to the underlying stream_buf
|
||||
basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
|
||||
basic_pipebuf<CharT, Traits>* rdbuf() const {return _buf;};
|
||||
|
||||
///Default constructor.
|
||||
basic_pstream() : std::basic_iostream<CharT, Traits>(nullptr)
|
||||
@@ -439,10 +423,8 @@ public:
|
||||
///Copy constructor.
|
||||
basic_pstream(const basic_pstream & ) = delete;
|
||||
///Move constructor.
|
||||
basic_pstream(basic_pstream && lhs) : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf))
|
||||
{
|
||||
std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
|
||||
}
|
||||
basic_pstream(basic_pstream && ) = default;
|
||||
|
||||
///Move construct from a pipe.
|
||||
basic_pstream(pipe_type && p) : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(p))
|
||||
{
|
||||
@@ -456,12 +438,7 @@ public:
|
||||
///Copy assignment.
|
||||
basic_pstream& operator=(const basic_pstream & ) = delete;
|
||||
///Move assignment
|
||||
basic_pstream& operator=(basic_pstream && lhs)
|
||||
{
|
||||
std::basic_istream<CharT, Traits>::operator=(std::move(lhs));
|
||||
_buf = std::move(lhs);
|
||||
std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
|
||||
};
|
||||
basic_pstream& operator=(basic_pstream && ) = default;
|
||||
///Move assignment of a pipe.
|
||||
basic_pstream& operator=(pipe_type && p)
|
||||
{
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <boost/process/detail/config.hpp>
|
||||
#include <boost/process/detail/handler.hpp>
|
||||
#include <boost/process/locale.hpp>
|
||||
#include <boost/process/detail/traits/wchar_t.hpp>
|
||||
|
||||
#if defined (BOOST_POSIX_API)
|
||||
#include <boost/process/detail/posix/start_dir.hpp>
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <boost/process/child.hpp>
|
||||
#include <boost/process/detail/async_handler.hpp>
|
||||
#include <boost/process/detail/execute_impl.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <type_traits>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
@@ -63,7 +62,7 @@ inline int system_impl(
|
||||
::boost::process::on_exit(
|
||||
[&](int, const std::error_code&)
|
||||
{
|
||||
boost::asio::post(ios.get_executor(), [&]{exited.store(true);});
|
||||
ios.post([&]{exited.store(true);});
|
||||
}));
|
||||
if (!c.valid() || !check.succeeded)
|
||||
return -1;
|
||||
@@ -86,8 +85,6 @@ inline int system_impl(
|
||||
return -1;
|
||||
|
||||
ios.run();
|
||||
if (c.running())
|
||||
c.wait();
|
||||
return c.exit_code();
|
||||
}
|
||||
|
||||
|
||||
104
test/Jamfile.jam
104
test/Jamfile.jam
@@ -19,7 +19,6 @@ if [ os.name ] = NT
|
||||
}
|
||||
|
||||
project : requirements
|
||||
<define>BOOST_ASIO_NO_DEPRECATED
|
||||
<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
|
||||
<toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
|
||||
<toolset>msvc:<cxxflags>/bigobj
|
||||
@@ -53,73 +52,64 @@ exe exit_argc : exit_argc.cpp :
|
||||
|
||||
exe sub_launch : sub_launcher.cpp program_options iostreams system filesystem : <warnings>off <target-os>windows:<source>shell32 ;
|
||||
|
||||
rule test-options ( name )
|
||||
{
|
||||
return --log_sink=log_$(name).xml --log_format=XML --log_level=error --report_sink=report_$(name).xml --report_format=XML --report_level=detailed -- ;
|
||||
}
|
||||
|
||||
|
||||
test-suite bare :
|
||||
[ run environment.cpp system filesystem : [ test-options environment ] ]
|
||||
[ run async_pipe.cpp system filesystem : [ test-options async_pipe ] ]
|
||||
[ run pipe.cpp system filesystem : [ test-options pipe ] ]
|
||||
[ run environment.cpp system filesystem ]
|
||||
[ run async_pipe.cpp system filesystem ]
|
||||
[ run pipe.cpp system filesystem ]
|
||||
[ compile no_ansi_apps.cpp ]
|
||||
[ compile-fail spawn_fail.cpp ]
|
||||
[ compile-fail async_system_fail.cpp ]
|
||||
[ compile asio_no_deprecated.cpp ]
|
||||
;
|
||||
|
||||
echo [ test-options foo ] ;
|
||||
|
||||
test-suite with-valgrind :
|
||||
[ run async.cpp system thread filesystem : [ test-options async ] : sparring_partner ]
|
||||
[ run async_fut.cpp system thread filesystem : [ test-options async_fut ] : sparring_partner ]
|
||||
[ run args_handling.cpp system thread filesystem : [ test-options args_handling ] : exit_argc ]
|
||||
[ run args_cmd.cpp system filesystem : [ test-options args_cmd ] : sparring_partner ]
|
||||
[ run wargs_cmd.cpp system filesystem : [ test-options wargs_cmd ] : sparring_partner ]
|
||||
[ run bind_stderr.cpp filesystem : [ test-options bind_stderr ] : sparring_partner ]
|
||||
[ run bind_stdin.cpp system filesystem : [ test-options bind_stdin ] : sparring_partner ]
|
||||
[ run bind_stdin_stdout.cpp system filesystem : [ test-options bind_stdin_stdout ] : sparring_partner ]
|
||||
[ run bind_stdout.cpp system filesystem : [ test-options bind_stdout ] : sparring_partner ]
|
||||
[ run bind_stdout_stderr.cpp system filesystem : [ test-options bind_stdout_stderr ] : sparring_partner ]
|
||||
[ run pipe_fwd.cpp system filesystem : [ test-options pipe_fwd ] : sparring_partner ]
|
||||
[ run cmd_test.cpp system filesystem : [ test-options cmd_test ] : sparring_partner ]
|
||||
[ run close_stderr.cpp system filesystem : [ test-options close_stderr ] : sparring_partner ]
|
||||
[ run close_stdin.cpp system filesystem : [ test-options close_stdin ] : sparring_partner ]
|
||||
[ run close_stdout.cpp system filesystem : [ test-options close_stdout ] : sparring_partner ]
|
||||
[ run error.cpp system filesystem : [ test-options error ] : sparring_partner ]
|
||||
[ run exit_code.cpp program_options system filesystem : [ test-options exit_code ] : sparring_partner ]
|
||||
[ run extensions.cpp system filesystem : [ test-options extensions ] : sparring_partner ]
|
||||
[ run env.cpp program_options system filesystem : [ test-options env ] : sparring_partner ]
|
||||
[ run group.cpp system thread filesystem : [ test-options group ] : sub_launch ]
|
||||
[ run group.cpp system thread filesystem : [ test-options group ] : sub_launch : <build>no <target-os>windows:<build>yes <define>BOOST_USE_WINDOWS_H=1 : group-windows-h ]
|
||||
[ run group_wait.cpp system thread filesystem : [ test-options group_wait ] : sparring_partner ]
|
||||
[ run async.cpp system thread filesystem : : sparring_partner ]
|
||||
[ run async_fut.cpp system thread filesystem : : sparring_partner ]
|
||||
[ run args_handling.cpp system thread filesystem : : exit_argc ]
|
||||
[ run args_cmd.cpp system filesystem : : sparring_partner ]
|
||||
[ run wargs_cmd.cpp system filesystem : : sparring_partner ]
|
||||
[ run bind_stderr.cpp filesystem : : sparring_partner ]
|
||||
[ run bind_stdin.cpp system filesystem : : sparring_partner ]
|
||||
[ run bind_stdin_stdout.cpp system filesystem : : sparring_partner ]
|
||||
[ run bind_stdout.cpp system filesystem : : sparring_partner ]
|
||||
[ run bind_stdout_stderr.cpp system filesystem : : sparring_partner ]
|
||||
[ run pipe_fwd.cpp system filesystem : : sparring_partner ]
|
||||
[ run cmd_test.cpp system filesystem : : sparring_partner ]
|
||||
[ run close_stderr.cpp system filesystem : : sparring_partner ]
|
||||
[ run close_stdin.cpp system filesystem : : sparring_partner ]
|
||||
[ run close_stdout.cpp system filesystem : : sparring_partner ]
|
||||
[ run error.cpp system filesystem : : sparring_partner ]
|
||||
[ run exit_code.cpp program_options system filesystem : : sparring_partner ]
|
||||
[ run extensions.cpp system filesystem : : sparring_partner ]
|
||||
[ run env.cpp program_options system filesystem : : sparring_partner ]
|
||||
[ run group.cpp system thread filesystem : : sub_launch ]
|
||||
[ run run_exe.cpp filesystem : : sparring_partner ]
|
||||
[ run run_exe_path.cpp filesystem : [ test-options run_exe_path ] : sparring_partner ]
|
||||
[ run search_path.cpp filesystem system : [ test-options search_path ] : : <target-os>windows:<source>shell32 ]
|
||||
[ run shell.cpp filesystem system : [ test-options shell ] : sparring_partner ]
|
||||
[ run shell_path.cpp filesystem system : [ test-options shell_path ] ]
|
||||
[ run system_test1.cpp filesystem system : [ test-options system_test1 ] : sparring_partner ]
|
||||
[ run system_test2.cpp filesystem system : [ test-options system_test2 ] : sparring_partner ]
|
||||
[ run spawn.cpp filesystem system : [ test-options spawn ] : sparring_partner ]
|
||||
[ run start_dir.cpp filesystem system : [ test-options start_dir ] : sparring_partner ]
|
||||
[ run terminate.cpp system filesystem : [ test-options terminate ] : sparring_partner ]
|
||||
[ run throw_on_error.cpp system filesystem : [ test-options throw_on_error ] : sparring_partner ]
|
||||
[ run wait.cpp system filesystem : [ test-options wait ] : sparring_partner ]
|
||||
[ run wait_for.cpp system filesystem : [ test-options wait_for ] : sparring_partner ]
|
||||
[ run on_exit.cpp system filesystem : [ test-options on_exit ] : sparring_partner ]
|
||||
[ run on_exit2.cpp system filesystem : [ test-options on_exit2 ] : sparring_partner ]
|
||||
[ run on_exit3.cpp system filesystem : [ test-options on_exit3 ] : sparring_partner ]
|
||||
[ run posix_specific.cpp system filesystem : [ test-options posix_specific ] : sparring_partner : <build>no <target-os>linux:<build>yes ]
|
||||
[ run windows_specific.cpp filesystem system : [ test-options windows_specific ] : sparring_partner : <build>no <target-os>windows:<build>yes ]
|
||||
[ run run_exe_path.cpp filesystem : : sparring_partner ]
|
||||
[ run search_path.cpp filesystem system : : : <target-os>windows:<source>shell32 ]
|
||||
[ run shell.cpp filesystem system : : sparring_partner ]
|
||||
[ run shell_path.cpp filesystem system ]
|
||||
[ run system_test1.cpp filesystem system : : sparring_partner ]
|
||||
[ run system_test2.cpp filesystem system : : sparring_partner ]
|
||||
[ run spawn.cpp filesystem system : : sparring_partner ]
|
||||
[ run start_dir.cpp filesystem system : : sparring_partner ]
|
||||
[ run terminate.cpp system filesystem : : sparring_partner ]
|
||||
[ run throw_on_error.cpp system filesystem : : sparring_partner ]
|
||||
[ run wait.cpp system filesystem : : sparring_partner ]
|
||||
[ run wait_for.cpp system filesystem : : sparring_partner ]
|
||||
[ run on_exit.cpp system filesystem : : sparring_partner ]
|
||||
[ run on_exit2.cpp system filesystem : : sparring_partner ]
|
||||
[ run on_exit3.cpp system filesystem : : sparring_partner ]
|
||||
[ run posix_specific.cpp system filesystem : : sparring_partner : <build>no <target-os>linux:<build>yes ]
|
||||
[ run windows_specific.cpp filesystem system : : sparring_partner : <build>no <target-os>windows:<build>yes ]
|
||||
: <dependency>bare ;
|
||||
|
||||
test-suite without-valgrind :
|
||||
[ run async_system_future.cpp filesystem system coroutine : [ test-options async_system_future ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run async_system_stackful.cpp filesystem system coroutine : [ test-options async_system_stackful ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run async_system_stackful_error.cpp filesystem system coroutine : [ test-options async_system_stackful_error ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run async_system_stackful_except.cpp filesystem system coroutine : [ test-options async_system_stackful_except ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run async_system_stackless.cpp filesystem system coroutine : [ test-options async_system_stackless ] : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run vfork.cpp system filesystem : [ test-options vfork ] : sparring_partner : <build>no <target-os>linux:<build>yes ]
|
||||
[ run async_system_future.cpp filesystem system coroutine : : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run async_system_stackful.cpp filesystem system coroutine : : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run async_system_stackful_error.cpp filesystem system coroutine : : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run async_system_stackful_except.cpp filesystem system coroutine : : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run async_system_stackless.cpp filesystem system coroutine : : sparring_partner : <link>static <toolset>msvc:<cxxflags>/bigobj ]
|
||||
[ run vfork.cpp system filesystem : : sparring_partner : <build>no <target-os>linux:<build>yes ]
|
||||
;
|
||||
|
||||
|
||||
|
||||
@@ -17,13 +17,12 @@ init:
|
||||
os: Visual Studio 2015
|
||||
configuration: Debug
|
||||
platform: x64
|
||||
build: off
|
||||
|
||||
###############################################################################################################
|
||||
# From this point and below code is same for all the Boost libs
|
||||
###############################################################################################################
|
||||
|
||||
version: 1.69.{build}-{branch}
|
||||
version: 1.61.{build}-{branch}
|
||||
|
||||
# branches to build
|
||||
branches:
|
||||
@@ -73,5 +72,3 @@ after_test:
|
||||
on_success:
|
||||
on_failure:
|
||||
on_finish:
|
||||
- curl -s https://report.ci/upload.py | python - --name "windows test run" --root_dir=%BOOST%/libs/%PROJECT_TO_TEST%/test
|
||||
|
||||
|
||||
13
test/asio_no_deprecated.cpp
Normal file
13
test/asio_no_deprecated.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// Created by kleme on 26.02.2018.
|
||||
//
|
||||
|
||||
#define BOOST_ASIO_NO_DEPRECATED 1
|
||||
#include <boost/process.hpp>
|
||||
int main() {}
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
#include <boost/process/posix.hpp>
|
||||
#elif
|
||||
#include <boost/process/windows.hpp>
|
||||
#endif
|
||||
127
test/async.cpp
127
test/async.cpp
@@ -8,7 +8,7 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
//#define BOOST_TEST_IGNORE_SIGCHLD
|
||||
#define BOOST_TEST_IGNORE_SIGCHLD
|
||||
#include <boost/test/included/unit_test.hpp>
|
||||
|
||||
#include <boost/process/error.hpp>
|
||||
@@ -20,21 +20,15 @@
|
||||
#include <future>
|
||||
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace bp = boost::process;
|
||||
|
||||
#if __APPLE__
|
||||
auto abort_sig = signal(SIGALRM, +[](int){std::terminate();});
|
||||
#endif
|
||||
|
||||
BOOST_AUTO_TEST_SUITE( async );
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(5))
|
||||
BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(2))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
using namespace boost::asio;
|
||||
@@ -45,34 +39,34 @@ BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(5))
|
||||
|
||||
bool exit_called_for_c1 = false;
|
||||
int exit_code_c1 = 0;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
bp::child c1(master_test_suite().argv[1],
|
||||
"test", "--exit-code", "123",
|
||||
ec, io_context,
|
||||
bp::on_exit([&](int exit, const std::error_code& ec_in)
|
||||
{
|
||||
BOOST_CHECK(!exit_called_for_c1);
|
||||
exit_code_c1 = exit; exit_called_for_c1=true;
|
||||
BOOST_CHECK(!ec_in);
|
||||
timeout.cancel();
|
||||
}));
|
||||
bp::child c1(
|
||||
master_test_suite().argv[1],
|
||||
"test", "--exit-code", "123",
|
||||
ec,
|
||||
io_context,
|
||||
bp::on_exit([&](int exit, const std::error_code& ec_in)
|
||||
{
|
||||
BOOST_CHECK(!exit_called_for_c1);
|
||||
exit_code_c1 = exit; exit_called_for_c1=true;
|
||||
BOOST_CHECK(!ec_in);
|
||||
})
|
||||
);
|
||||
BOOST_REQUIRE(!ec);
|
||||
|
||||
bool exit_called_for_c2 = false;
|
||||
int exit_code_c2 = 0;
|
||||
bp::child c2(master_test_suite().argv[1],
|
||||
"test", "--exit-code", "21",
|
||||
ec, io_context,
|
||||
bp::on_exit([&](int exit, const std::error_code& ec_in)
|
||||
{
|
||||
BOOST_CHECK(!exit_called_for_c2);
|
||||
exit_code_c2 = exit; exit_called_for_c2=true;
|
||||
BOOST_CHECK(!ec_in);
|
||||
})
|
||||
);
|
||||
bp::child c2(
|
||||
master_test_suite().argv[1],
|
||||
"test", "--exit-code", "21",
|
||||
ec,
|
||||
io_context,
|
||||
bp::on_exit([&](int exit, const std::error_code& ec_in)
|
||||
{
|
||||
BOOST_CHECK(!exit_called_for_c2);
|
||||
exit_code_c2 = exit; exit_called_for_c2=true;
|
||||
BOOST_CHECK(!ec_in);
|
||||
})
|
||||
);
|
||||
BOOST_REQUIRE(!ec);
|
||||
|
||||
io_context.run();
|
||||
@@ -86,7 +80,7 @@ BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(5))
|
||||
BOOST_CHECK_EQUAL(c2.exit_code(), 21);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_wait_sync_wait, *boost::unit_test::timeout(5))
|
||||
BOOST_AUTO_TEST_CASE(async_wait_sync_wait, *boost::unit_test::timeout(3))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
using namespace boost::asio;
|
||||
@@ -96,10 +90,6 @@ BOOST_AUTO_TEST_CASE(async_wait_sync_wait, *boost::unit_test::timeout(5))
|
||||
bool exit_called = false;
|
||||
int exit_code = 0;
|
||||
std::error_code ec;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(3)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
bp::child c1(
|
||||
master_test_suite().argv[1],
|
||||
"test", "--exit-code", "1",
|
||||
@@ -116,7 +106,6 @@ BOOST_AUTO_TEST_CASE(async_wait_sync_wait, *boost::unit_test::timeout(5))
|
||||
{
|
||||
exit_code = exit; exit_called=true;
|
||||
BOOST_CHECK(!ec_in);
|
||||
timeout.cancel();
|
||||
})
|
||||
);
|
||||
BOOST_REQUIRE(!ec);
|
||||
@@ -132,7 +121,7 @@ BOOST_AUTO_TEST_CASE(async_wait_sync_wait, *boost::unit_test::timeout(5))
|
||||
BOOST_CHECK_EQUAL(c2.exit_code(), 2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_wait_different_contexts, *boost::unit_test::timeout(10))
|
||||
BOOST_AUTO_TEST_CASE(async_wait_different_contexts, *boost::unit_test::timeout(3))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
using namespace boost::asio;
|
||||
@@ -140,11 +129,6 @@ BOOST_AUTO_TEST_CASE(async_wait_different_contexts, *boost::unit_test::timeout(1
|
||||
boost::asio::io_context io_context1;
|
||||
boost::asio::io_context io_context2;
|
||||
|
||||
boost::asio::deadline_timer timeout1{io_context1, boost::posix_time::seconds(2)};
|
||||
timeout1.async_wait([&](boost::system::error_code ec){if (!ec) io_context1.stop();});
|
||||
|
||||
boost::asio::deadline_timer timeout2{io_context2, boost::posix_time::seconds(7)};
|
||||
timeout2.async_wait([&](boost::system::error_code ec){if (!ec) io_context2.stop();});
|
||||
std::error_code ec;
|
||||
|
||||
bool exit_called_for_c1 = false;
|
||||
@@ -159,7 +143,6 @@ BOOST_AUTO_TEST_CASE(async_wait_different_contexts, *boost::unit_test::timeout(1
|
||||
BOOST_CHECK(!exit_called_for_c1);
|
||||
exit_code_c1 = exit; exit_called_for_c1=true;
|
||||
BOOST_CHECK(!ec_in);
|
||||
timeout1.cancel();
|
||||
})
|
||||
);
|
||||
BOOST_REQUIRE(!ec);
|
||||
@@ -168,7 +151,7 @@ BOOST_AUTO_TEST_CASE(async_wait_different_contexts, *boost::unit_test::timeout(1
|
||||
int exit_code_c2 = 0;
|
||||
bp::child c2(
|
||||
master_test_suite().argv[1],
|
||||
"test", "--exit-code", "2", "--wait", "4",
|
||||
"test", "--exit-code", "2", "--wait", "1",
|
||||
ec,
|
||||
io_context2,
|
||||
bp::on_exit([&](int exit, const std::error_code& ec_in)
|
||||
@@ -176,17 +159,13 @@ BOOST_AUTO_TEST_CASE(async_wait_different_contexts, *boost::unit_test::timeout(1
|
||||
BOOST_CHECK(!exit_called_for_c2);
|
||||
exit_code_c2 = exit; exit_called_for_c2=true;
|
||||
BOOST_CHECK(!ec_in);
|
||||
timeout2.cancel();
|
||||
})
|
||||
);
|
||||
BOOST_REQUIRE(!ec);
|
||||
|
||||
// Regression test for #143: make sure each io_context handles its own children
|
||||
std::thread thr1{[&]{io_context1.run();}};
|
||||
std::thread thr2{[&]{io_context2.run();}};
|
||||
|
||||
thr1.join();
|
||||
thr2.join();
|
||||
io_context2.run();
|
||||
io_context1.run();
|
||||
c1.wait(ec);
|
||||
BOOST_REQUIRE(!ec);
|
||||
|
||||
@@ -198,7 +177,7 @@ BOOST_AUTO_TEST_CASE(async_wait_different_contexts, *boost::unit_test::timeout(1
|
||||
BOOST_CHECK_EQUAL(c2.exit_code(), 2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_wait_abort, *boost::unit_test::timeout(5))
|
||||
BOOST_AUTO_TEST_CASE(async_wait_abort, *boost::unit_test::timeout(2))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
using namespace boost::asio;
|
||||
@@ -207,9 +186,6 @@ BOOST_AUTO_TEST_CASE(async_wait_abort, *boost::unit_test::timeout(5))
|
||||
|
||||
std::error_code ec;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(5)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
bool exit_called = false;
|
||||
int exit_code = 0;
|
||||
bp::child c(
|
||||
@@ -220,11 +196,9 @@ BOOST_AUTO_TEST_CASE(async_wait_abort, *boost::unit_test::timeout(5))
|
||||
bp::on_exit([&](int exit, const std::error_code& ec_in)
|
||||
{
|
||||
BOOST_CHECK(!exit_called);
|
||||
exit_code = exit;
|
||||
exit_called=true;
|
||||
exit_code = exit; exit_called=true;
|
||||
BOOST_TEST_MESSAGE(ec_in.message());
|
||||
BOOST_CHECK(!ec_in);
|
||||
timeout.cancel();
|
||||
})
|
||||
);
|
||||
BOOST_REQUIRE(!ec);
|
||||
@@ -232,21 +206,18 @@ BOOST_AUTO_TEST_CASE(async_wait_abort, *boost::unit_test::timeout(5))
|
||||
io_context.run();
|
||||
|
||||
BOOST_CHECK(exit_called);
|
||||
BOOST_CHECK_NE(exit_code, 0);
|
||||
BOOST_CHECK(exit_code != 0);
|
||||
BOOST_CHECK_EQUAL(c.exit_code(), exit_code);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_future, *boost::unit_test::timeout(3))
|
||||
BOOST_AUTO_TEST_CASE(async_future, *boost::unit_test::timeout(2))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
using namespace boost::asio;
|
||||
|
||||
boost::asio::io_context io_context;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
std::error_code ec;
|
||||
std::future<int> fut;
|
||||
bp::child c(
|
||||
@@ -258,15 +229,13 @@ BOOST_AUTO_TEST_CASE(async_future, *boost::unit_test::timeout(3))
|
||||
);
|
||||
|
||||
BOOST_REQUIRE(!ec);
|
||||
|
||||
io_context.run();
|
||||
|
||||
BOOST_REQUIRE(fut.valid());
|
||||
BOOST_CHECK_EQUAL(fut.get(), 42);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_out_stream, *boost::unit_test::timeout(5))
|
||||
BOOST_AUTO_TEST_CASE(async_out_stream, *boost::unit_test::timeout(2))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
@@ -277,9 +246,6 @@ BOOST_AUTO_TEST_CASE(async_out_stream, *boost::unit_test::timeout(5))
|
||||
|
||||
boost::asio::streambuf buf;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
bp::child c(master_test_suite().argv[1],
|
||||
"test", "--echo-stdout", "abc",
|
||||
bp::std_out > buf,
|
||||
@@ -287,8 +253,8 @@ BOOST_AUTO_TEST_CASE(async_out_stream, *boost::unit_test::timeout(5))
|
||||
ec);
|
||||
BOOST_REQUIRE(!ec);
|
||||
|
||||
io_context.run();
|
||||
|
||||
io_context.run();
|
||||
std::istream istr(&buf);
|
||||
|
||||
std::string line;
|
||||
@@ -300,7 +266,7 @@ BOOST_AUTO_TEST_CASE(async_out_stream, *boost::unit_test::timeout(5))
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_in_stream, *boost::unit_test::timeout(5))
|
||||
BOOST_AUTO_TEST_CASE(async_in_stream, *boost::unit_test::timeout(2))
|
||||
{
|
||||
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
@@ -317,9 +283,6 @@ BOOST_AUTO_TEST_CASE(async_in_stream, *boost::unit_test::timeout(5))
|
||||
std::ostream ostr(&in_buf);
|
||||
ostr << "-string" << endl ;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
bp::child c(
|
||||
master_test_suite().argv[1],
|
||||
"test", "--prefix-once", "test",
|
||||
@@ -330,8 +293,8 @@ BOOST_AUTO_TEST_CASE(async_in_stream, *boost::unit_test::timeout(5))
|
||||
);
|
||||
BOOST_REQUIRE(!ec);
|
||||
|
||||
io_context.run();
|
||||
|
||||
io_context.run();
|
||||
std::istream istr(&buf);
|
||||
|
||||
std::string line;
|
||||
@@ -347,16 +310,13 @@ BOOST_AUTO_TEST_CASE(async_in_stream, *boost::unit_test::timeout(5))
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_error, *boost::unit_test::timeout(3))
|
||||
BOOST_AUTO_TEST_CASE(async_error, *boost::unit_test::timeout(2))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
using namespace boost::asio;
|
||||
|
||||
boost::asio::io_context io_context;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(2)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
bool exit_called = false;
|
||||
std::error_code ec;
|
||||
bp::child c(
|
||||
@@ -370,10 +330,7 @@ BOOST_AUTO_TEST_CASE(async_error, *boost::unit_test::timeout(3))
|
||||
);
|
||||
|
||||
BOOST_REQUIRE(ec);
|
||||
|
||||
io_context.run();
|
||||
|
||||
BOOST_CHECK(!exit_called);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -24,8 +24,6 @@
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE( async );
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -103,4 +101,3 @@ BOOST_AUTO_TEST_CASE(emtpy_out, *boost::unit_test::timeout(2))
|
||||
BOOST_CHECK_EQUAL(fut.get(), "");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -23,9 +23,6 @@ using namespace std;
|
||||
namespace bp = boost::process;
|
||||
namespace asio = boost::asio;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE( async );
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(plain_async, *boost::unit_test::timeout(5))
|
||||
{
|
||||
asio::io_context ios;
|
||||
@@ -86,5 +83,3 @@ BOOST_AUTO_TEST_CASE(multithreaded_async_pipe)
|
||||
for (auto &t : threads)
|
||||
t.join();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <array>
|
||||
|
||||
namespace bp = boost::process;
|
||||
BOOST_AUTO_TEST_SUITE( async );
|
||||
|
||||
BOOST_AUTO_TEST_CASE(future, *boost::unit_test::timeout(15))
|
||||
{
|
||||
@@ -60,5 +59,3 @@ BOOST_AUTO_TEST_CASE(future_error, *boost::unit_test::timeout(15))
|
||||
int exit_code = 0;
|
||||
BOOST_CHECK_THROW(exit_code = fut.get(), boost::system::system_error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include <string>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/asio/coroutine.hpp>
|
||||
#include <boost/asio/use_future.hpp>
|
||||
@@ -23,7 +22,6 @@
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
BOOST_AUTO_TEST_SUITE( async );
|
||||
|
||||
namespace bp = boost::process;
|
||||
BOOST_AUTO_TEST_CASE(stackful, *boost::unit_test::timeout(15))
|
||||
@@ -47,10 +45,8 @@ BOOST_AUTO_TEST_CASE(stackful, *boost::unit_test::timeout(15))
|
||||
};
|
||||
|
||||
boost::asio::spawn(ios, stackful);
|
||||
boost::asio::post(ios.get_executor(), [&]{did_something_else = true;});
|
||||
ios.post([&]{did_something_else = true;});
|
||||
|
||||
ios.run();
|
||||
BOOST_CHECK(did_something_else);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include <string>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/asio/coroutine.hpp>
|
||||
#include <boost/asio/use_future.hpp>
|
||||
@@ -23,7 +22,6 @@
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
BOOST_AUTO_TEST_SUITE( async );
|
||||
|
||||
namespace bp = boost::process;
|
||||
BOOST_AUTO_TEST_CASE(stackful, *boost::unit_test::timeout(15))
|
||||
@@ -47,7 +45,7 @@ BOOST_AUTO_TEST_CASE(stackful, *boost::unit_test::timeout(15))
|
||||
};
|
||||
|
||||
boost::asio::spawn(ios, stackful);
|
||||
boost::asio::post(ios.get_executor(), [&]{did_something_else = true;});
|
||||
ios.post([&]{did_something_else = true;});
|
||||
|
||||
ios.run();
|
||||
BOOST_CHECK(did_something_else);
|
||||
@@ -73,7 +71,7 @@ BOOST_AUTO_TEST_CASE(stackful_except, *boost::unit_test::timeout(15))
|
||||
};
|
||||
|
||||
boost::asio::spawn(ios, stackful);
|
||||
boost::asio::post(ios.get_executor(), [&]{did_something_else = true;});
|
||||
ios.post([&]{did_something_else = true;});
|
||||
ios.run();
|
||||
|
||||
BOOST_CHECK(did_something_else);
|
||||
@@ -102,10 +100,8 @@ BOOST_AUTO_TEST_CASE(stackful_error, *boost::unit_test::timeout(15))
|
||||
};
|
||||
|
||||
boost::asio::spawn(ios, stackful);
|
||||
boost::asio::post(ios.get_executor(), [&]{did_something_else = true;});
|
||||
ios.post([&]{did_something_else = true;});
|
||||
ios.run();
|
||||
|
||||
BOOST_CHECK(did_something_else);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
}
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include <string>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/asio/coroutine.hpp>
|
||||
#include <boost/asio/use_future.hpp>
|
||||
@@ -23,7 +22,6 @@
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
BOOST_AUTO_TEST_SUITE( async );
|
||||
|
||||
namespace bp = boost::process;
|
||||
BOOST_AUTO_TEST_CASE(stackful_except, *boost::unit_test::timeout(15))
|
||||
@@ -46,10 +44,10 @@ BOOST_AUTO_TEST_CASE(stackful_except, *boost::unit_test::timeout(15))
|
||||
};
|
||||
|
||||
boost::asio::spawn(ios, stackful);
|
||||
boost::asio::post(ios.get_executor(), [&]{did_something_else = true;});
|
||||
ios.post([&]{did_something_else = true;});
|
||||
ios.run();
|
||||
|
||||
BOOST_CHECK(did_something_else);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include <string>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/spawn.hpp>
|
||||
#include <boost/asio/coroutine.hpp>
|
||||
#include <boost/asio/use_future.hpp>
|
||||
@@ -23,7 +22,6 @@
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
BOOST_AUTO_TEST_SUITE( async );
|
||||
|
||||
namespace bp = boost::process;
|
||||
BOOST_AUTO_TEST_CASE(stackless, *boost::unit_test::timeout(15))
|
||||
@@ -59,13 +57,10 @@ BOOST_AUTO_TEST_CASE(stackless, *boost::unit_test::timeout(15))
|
||||
}
|
||||
} stackless{ios, did_something_else};
|
||||
|
||||
boost::asio::post(ios.get_executor(), [&]{stackless();});
|
||||
boost::asio::post(ios.get_executor(), [&]{did_something_else = true;});
|
||||
ios.post([&]{stackless();});
|
||||
ios.post([&]{did_something_else = true;});
|
||||
|
||||
ios.run();
|
||||
|
||||
BOOST_CHECK(did_something_else);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -39,7 +39,6 @@ typedef boost::asio::posix::stream_descriptor pipe_end;
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
namespace bp = boost::process;
|
||||
BOOST_AUTO_TEST_SUITE( bind_stderr );
|
||||
|
||||
BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(2))
|
||||
{
|
||||
@@ -151,5 +150,3 @@ BOOST_AUTO_TEST_CASE(file_io, *boost::unit_test::timeout(2))
|
||||
boost::filesystem::remove(pth);
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE( bind_stdin );
|
||||
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
# include <windows.h>
|
||||
@@ -256,5 +255,3 @@ BOOST_AUTO_TEST_CASE(file_io_C, *boost::unit_test::timeout(2))
|
||||
c.wait();
|
||||
boost::filesystem::remove(pth);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <iostream>
|
||||
|
||||
namespace bp = boost::process;
|
||||
BOOST_AUTO_TEST_SUITE( bind_stdin_stdout );
|
||||
|
||||
BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(10))
|
||||
{
|
||||
@@ -54,5 +53,3 @@ BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(10))
|
||||
|
||||
BOOST_CHECK(c.wait_for(std::chrono::seconds(3)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -37,9 +37,6 @@ typedef boost::asio::windows::stream_handle pipe_end;
|
||||
typedef boost::asio::posix::stream_descriptor pipe_end;
|
||||
#endif
|
||||
|
||||
BOOST_AUTO_TEST_SUITE( bind_stdout );
|
||||
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
namespace bp = boost::process;
|
||||
|
||||
@@ -167,5 +164,3 @@ BOOST_AUTO_TEST_CASE(file_io, *boost::unit_test::timeout(2))
|
||||
boost::filesystem::remove(pth);
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -35,9 +35,6 @@ typedef boost::asio::posix::stream_descriptor pipe_end;
|
||||
|
||||
namespace bp = boost::process;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE( bind_stdout_stderr );
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(2))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
@@ -134,5 +131,3 @@ BOOST_AUTO_TEST_CASE(nul, *boost::unit_test::timeout(2))
|
||||
BOOST_CHECK_EQUAL(EXIT_SUCCESS, exit_code);
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -25,7 +25,7 @@
|
||||
namespace bp = boost::process;
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(close_stderr)
|
||||
BOOST_AUTO_TEST_CASE(closed)
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
namespace bp = boost::process;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(close_stdin)
|
||||
BOOST_AUTO_TEST_CASE(closed)
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
namespace bp = boost::process;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(close_stdout)
|
||||
BOOST_AUTO_TEST_CASE(closed)
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
|
||||
#define BOOST_TEST_IGNORE_SIGCHLD
|
||||
#include <boost/test/included/unit_test.hpp>
|
||||
|
||||
#include <boost/process/error.hpp>
|
||||
@@ -72,12 +72,11 @@ BOOST_AUTO_TEST_CASE(sync_wait_abort)
|
||||
struct wait_handler
|
||||
{
|
||||
HANDLE handle_;
|
||||
bool &called_;
|
||||
wait_handler(HANDLE handle, bool &called) : handle_(handle), called_(called) {}
|
||||
|
||||
wait_handler(HANDLE handle) : handle_(handle) {}
|
||||
|
||||
void operator()(const boost::system::error_code &ec)
|
||||
{
|
||||
called_ = true;
|
||||
BOOST_REQUIRE(!ec);
|
||||
DWORD exit_code;
|
||||
BOOST_REQUIRE(GetExitCodeProcess(handle_, &exit_code));
|
||||
@@ -87,13 +86,8 @@ struct wait_handler
|
||||
#elif defined(BOOST_POSIX_API)
|
||||
struct wait_handler
|
||||
{
|
||||
bool &called_;
|
||||
|
||||
wait_handler (bool & called) : called_(called) {}
|
||||
|
||||
void operator()(const boost::system::error_code &ec, int signal)
|
||||
{
|
||||
called_ = true;
|
||||
BOOST_REQUIRE(!ec);
|
||||
BOOST_REQUIRE_EQUAL(SIGCHLD, signal);
|
||||
int status;
|
||||
@@ -110,14 +104,9 @@ BOOST_AUTO_TEST_CASE(async_wait)
|
||||
|
||||
boost::asio::io_context io_context;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(3)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
|
||||
bool wh_called = false;
|
||||
#if defined(BOOST_POSIX_API)
|
||||
signal_set set(io_context, SIGCHLD);
|
||||
set.async_wait(wait_handler(wh_called));
|
||||
set.async_wait(wait_handler());
|
||||
#endif
|
||||
|
||||
std::error_code ec;
|
||||
@@ -129,11 +118,10 @@ BOOST_AUTO_TEST_CASE(async_wait)
|
||||
BOOST_REQUIRE(!ec);
|
||||
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
windows::object_handle handle(io_context.get_executor(), c.native_handle());
|
||||
handle.async_wait(wait_handler(handle.native_handle(), wh_called));
|
||||
windows::object_handle handle(io_context, c.native_handle());
|
||||
handle.async_wait(wait_handler(handle.native_handle()));
|
||||
#endif
|
||||
std::cout << "async_wait 1" << std::endl;
|
||||
io_context.run();
|
||||
std::cout << "async_wait 2" << std::endl;
|
||||
BOOST_CHECK_MESSAGE(wh_called, "Wait handler not called");
|
||||
}
|
||||
|
||||
@@ -28,6 +28,14 @@
|
||||
#include <istream>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
# include <windows.h>
|
||||
typedef boost::asio::windows::stream_handle pipe_end;
|
||||
#elif defined(BOOST_POSIX_API)
|
||||
# include <sys/wait.h>
|
||||
# include <unistd.h>
|
||||
typedef boost::asio::posix::stream_descriptor pipe_end;
|
||||
#endif
|
||||
|
||||
namespace bp = boost::process;
|
||||
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
|
||||
//
|
||||
// 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)
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
#define BOOST_TEST_IGNORE_SIGCHLD
|
||||
#include <boost/test/included/unit_test.hpp>
|
||||
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
#include <boost/process/error.hpp>
|
||||
#include <boost/process/io.hpp>
|
||||
#include <boost/process/args.hpp>
|
||||
#include <boost/process/child.hpp>
|
||||
#include <boost/process/group.hpp>
|
||||
#include <system_error>
|
||||
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <istream>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace bp = boost::process;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(wait_group_test, *boost::unit_test::timeout(5))
|
||||
{
|
||||
std::atomic<bool> done{false};
|
||||
std::thread thr{
|
||||
[&]
|
||||
{
|
||||
for (int i = 0; i < 50 && !done.load(); i++)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
BOOST_REQUIRE(done.load());
|
||||
}};
|
||||
|
||||
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
std::error_code ec;
|
||||
bp::group g;
|
||||
|
||||
|
||||
bp::child c1(
|
||||
master_test_suite().argv[1],
|
||||
"--wait", "2",
|
||||
g,
|
||||
ec
|
||||
);
|
||||
|
||||
bp::child c2(
|
||||
master_test_suite().argv[1],
|
||||
"--wait", "2",
|
||||
g,
|
||||
ec
|
||||
);
|
||||
|
||||
BOOST_CHECK(c1.running());
|
||||
BOOST_CHECK(c2.running());
|
||||
|
||||
BOOST_REQUIRE(!ec);
|
||||
BOOST_REQUIRE(c1.in_group(ec));
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
BOOST_REQUIRE(c2.in_group(ec));
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
g.wait();
|
||||
|
||||
BOOST_CHECK(!c1.running());
|
||||
BOOST_CHECK(!c2.running());
|
||||
|
||||
done.store(true);
|
||||
thr.join();
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(wait_group_test_timeout, *boost::unit_test::timeout(15))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
std::atomic<bool> done{false};
|
||||
std::thread thr{
|
||||
[&]
|
||||
{
|
||||
for (int i = 0; i < 150 && !done.load(); i++)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
BOOST_REQUIRE(done.load());
|
||||
}};
|
||||
|
||||
std::error_code ec;
|
||||
bp::group g;
|
||||
|
||||
|
||||
bp::child c1(
|
||||
master_test_suite().argv[1],
|
||||
"--wait", "1",
|
||||
g,
|
||||
ec
|
||||
);
|
||||
|
||||
bp::child c2(
|
||||
master_test_suite().argv[1],
|
||||
"--wait", "3",
|
||||
g,
|
||||
ec
|
||||
);
|
||||
|
||||
BOOST_CHECK(c1.running());
|
||||
BOOST_CHECK(c2.running());
|
||||
|
||||
BOOST_REQUIRE(!ec);
|
||||
BOOST_REQUIRE(c1.in_group());
|
||||
BOOST_REQUIRE(c2.in_group());
|
||||
|
||||
BOOST_CHECK(!g.wait_for(std::chrono::seconds(2), ec));
|
||||
|
||||
BOOST_CHECK_MESSAGE(!ec, std::to_string(ec.value()) + " == " + ec.message());
|
||||
BOOST_CHECK(!c1.running());
|
||||
BOOST_CHECK(c2.running());
|
||||
|
||||
BOOST_CHECK(g.wait_for(std::chrono::seconds(5), ec));
|
||||
BOOST_CHECK_MESSAGE(!ec, std::to_string(ec.value()) + " == " + ec.message());
|
||||
BOOST_CHECK(!c1.running());
|
||||
BOOST_CHECK(!c2.running());
|
||||
|
||||
done.store(true);
|
||||
thr.join();
|
||||
}
|
||||
@@ -3,8 +3,5 @@
|
||||
// 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/system/api_config.hpp>
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
#define BOOST_NO_ANSI_APIS 1
|
||||
#endif
|
||||
#include <boost/process.hpp>
|
||||
@@ -15,9 +15,6 @@
|
||||
using namespace std;
|
||||
namespace bp = boost::process;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE( pipe_tests );
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(plain, *boost::unit_test::timeout(2))
|
||||
{
|
||||
bp::pipe pipe;
|
||||
@@ -233,4 +230,3 @@ BOOST_AUTO_TEST_CASE(coverage, *boost::unit_test::timeout(5))
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -27,7 +27,6 @@
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE( pipe_tests );
|
||||
|
||||
namespace bp = boost::process;
|
||||
|
||||
@@ -75,4 +74,3 @@ BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(5))
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -41,7 +41,7 @@ typedef boost::asio::posix::stream_descriptor pipe_end;
|
||||
namespace fs = boost::filesystem;
|
||||
namespace bp = boost::process;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(sync_spawn, *boost::unit_test::timeout(5))
|
||||
BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(5))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
@@ -83,7 +83,7 @@ struct read_handler
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_spawn, *boost::unit_test::timeout(2))
|
||||
BOOST_AUTO_TEST_CASE(async_io, *boost::unit_test::timeout(2))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ typedef boost::asio::posix::stream_descriptor pipe_end;
|
||||
namespace fs = boost::filesystem;
|
||||
namespace bp = boost::process;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(system_exit_code, *boost::unit_test::timeout(5))
|
||||
BOOST_AUTO_TEST_CASE(exit_code, *boost::unit_test::timeout(5))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
@@ -67,15 +67,15 @@ BOOST_AUTO_TEST_CASE(implicit_async_io, *boost::unit_test::timeout(2))
|
||||
|
||||
std::future<std::string> fut;
|
||||
std::error_code ec;
|
||||
int res = bp::system(
|
||||
bp::system(
|
||||
master_test_suite().argv[1],
|
||||
"test", "--echo-stdout", "abc",
|
||||
bp::std_out > fut,
|
||||
ec
|
||||
);
|
||||
BOOST_REQUIRE(!ec);
|
||||
|
||||
BOOST_REQUIRE(fut.valid());
|
||||
BOOST_CHECK_EQUAL(res, 0);
|
||||
BOOST_CHECK(boost::starts_with(
|
||||
fut.get(), "abc"));
|
||||
}
|
||||
|
||||
@@ -70,19 +70,17 @@ BOOST_AUTO_TEST_CASE(explicit_async_io_running, *boost::unit_test::timeout(10))
|
||||
std::future<std::string> fut;
|
||||
std::error_code ec;
|
||||
|
||||
boost::asio::post(
|
||||
ios.get_executor(),
|
||||
[&] {
|
||||
bp::system(
|
||||
master_test_suite().argv[1],
|
||||
"test", "--echo-stdout", "abc",
|
||||
bp::std_out > fut,
|
||||
ios,
|
||||
ec
|
||||
);
|
||||
BOOST_REQUIRE(!ec);
|
||||
}
|
||||
);
|
||||
ios.post([&]
|
||||
{
|
||||
bp::system(
|
||||
master_test_suite().argv[1],
|
||||
"test", "--echo-stdout", "abc",
|
||||
bp::std_out > fut,
|
||||
ios,
|
||||
ec
|
||||
);
|
||||
BOOST_REQUIRE(!ec);
|
||||
});
|
||||
|
||||
|
||||
ios.run();
|
||||
|
||||
@@ -22,17 +22,8 @@
|
||||
|
||||
namespace bp = boost::process;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(terminate_set_on_error, *boost::unit_test::timeout(5))
|
||||
BOOST_AUTO_TEST_CASE(terminate_set_on_error)
|
||||
{
|
||||
std::atomic<bool> done{false};
|
||||
std::thread thr{
|
||||
[&]
|
||||
{
|
||||
for (int i = 0; i < 50 && !done.load(); i++)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
BOOST_REQUIRE(done.load());
|
||||
}};
|
||||
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
std::error_code ec;
|
||||
bp::child c(
|
||||
@@ -53,22 +44,10 @@ BOOST_AUTO_TEST_CASE(terminate_set_on_error, *boost::unit_test::timeout(5))
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
BOOST_CHECK(!c.running(ec));
|
||||
BOOST_CHECK(!ec);
|
||||
|
||||
done.store(true);
|
||||
thr.join();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(terminate_throw_on_error, *boost::unit_test::timeout(5))
|
||||
BOOST_AUTO_TEST_CASE(terminate_throw_on_error)
|
||||
{
|
||||
std::atomic<bool> done{false};
|
||||
std::thread thr{
|
||||
[&]
|
||||
{
|
||||
for (int i = 0; i < 50 && !done.load(); i++)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
BOOST_REQUIRE(done.load());
|
||||
}};
|
||||
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
std::error_code ec;
|
||||
@@ -89,7 +68,4 @@ BOOST_AUTO_TEST_CASE(terminate_throw_on_error, *boost::unit_test::timeout(5))
|
||||
c.terminate();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
BOOST_CHECK(!c.running());
|
||||
|
||||
done.store(true);
|
||||
thr.join();
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
|
||||
#define BOOST_TEST_IGNORE_SIGCHLD
|
||||
#include <boost/test/included/unit_test.hpp>
|
||||
#include <boost/process/error.hpp>
|
||||
#include <boost/process/child.hpp>
|
||||
@@ -24,9 +24,6 @@
|
||||
|
||||
namespace bp = boost::process;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE( wait_test );
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(sync_wait, *boost::unit_test::timeout(2))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
@@ -43,7 +40,7 @@ BOOST_AUTO_TEST_CASE(sync_wait, *boost::unit_test::timeout(2))
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(4))
|
||||
BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(2))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
using namespace boost::asio;
|
||||
@@ -53,10 +50,6 @@ BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(4))
|
||||
std::error_code ec;
|
||||
bool called = false;
|
||||
|
||||
boost::asio::deadline_timer timeout{io_context, boost::posix_time::seconds(3)};
|
||||
timeout.async_wait([&](boost::system::error_code ec){if (!ec) io_context.stop();});
|
||||
|
||||
|
||||
bp::child c(
|
||||
master_test_suite().argv[1],
|
||||
bp::args+={"test", "--wait", "1"},
|
||||
@@ -71,5 +64,3 @@ BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(4))
|
||||
BOOST_CHECK(called);
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
//#define BOOST_TEST_IGNORE_SIGCHLD
|
||||
#define BOOST_TEST_IGNORE_SIGCHLD
|
||||
#include <boost/test/included/unit_test.hpp>
|
||||
#include <boost/process/error.hpp>
|
||||
#include <boost/process/child.hpp>
|
||||
@@ -22,15 +22,12 @@
|
||||
#endif
|
||||
|
||||
namespace bp = boost::process;
|
||||
BOOST_AUTO_TEST_SUITE( wait_test);
|
||||
|
||||
BOOST_AUTO_TEST_CASE(wait_for)
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
std::error_code ec;
|
||||
|
||||
auto launch_time = std::chrono::system_clock::now();
|
||||
bp::child c(
|
||||
master_test_suite().argv[1],
|
||||
bp::args+={"test", "--wait", "1"},
|
||||
@@ -38,13 +35,8 @@ BOOST_AUTO_TEST_CASE(wait_for)
|
||||
);
|
||||
BOOST_REQUIRE(!ec);
|
||||
|
||||
|
||||
BOOST_CHECK(!c.wait_for(std::chrono::milliseconds(200)));
|
||||
BOOST_CHECK( c.wait_for(std::chrono::milliseconds(1000)));
|
||||
|
||||
auto timeout_t = std::chrono::system_clock::now();
|
||||
|
||||
BOOST_CHECK_LE(std::chrono::duration_cast<std::chrono::seconds>(timeout_t - launch_time).count(), 5); //should be less
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(wait_for_ec)
|
||||
@@ -109,6 +101,4 @@ BOOST_AUTO_TEST_CASE(wait_until_ec)
|
||||
BOOST_CHECK( c.wait_until(t2, ec));
|
||||
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
namespace bp = boost::process;
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(wargs, *boost::unit_test::timeout(2))
|
||||
BOOST_AUTO_TEST_CASE(args, *boost::unit_test::timeout(2))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
@@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE(wargs, *boost::unit_test::timeout(2))
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(wcmd, *boost::unit_test::timeout(2))
|
||||
BOOST_AUTO_TEST_CASE(cmd, *boost::unit_test::timeout(2))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user