mirror of
https://github.com/boostorg/process.git
synced 2026-01-20 16:52:14 +00:00
Compare commits
171 Commits
boost-1.69
...
sfinae_dyn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83c2a986cb | ||
|
|
41fff78e00 | ||
|
|
e85f0d0816 | ||
|
|
af54484bc2 | ||
|
|
ebcb30e4bd | ||
|
|
5371c9813b | ||
|
|
9a833c610d | ||
|
|
c99ebfee7a | ||
|
|
34861366e0 | ||
|
|
e6722c452c | ||
|
|
b1e38842fb | ||
|
|
bcc9826e67 | ||
|
|
b6c6753b87 | ||
|
|
0d008a88fc | ||
|
|
f92ec53968 | ||
|
|
00a87d0a67 | ||
|
|
462334639c | ||
|
|
7129182044 | ||
|
|
03fbed44ad | ||
|
|
0277c4fcec | ||
|
|
4bc1ae6ff8 | ||
|
|
266c4503aa | ||
|
|
80479b6b70 | ||
|
|
823a346a08 | ||
|
|
8f3a7b9c63 | ||
|
|
2ebcc07892 | ||
|
|
a673cd9643 | ||
|
|
12971db132 | ||
|
|
94be279992 | ||
|
|
12cded5995 | ||
|
|
0c16a0e5b3 | ||
|
|
e4a6fde7b9 | ||
|
|
92d2bebaaf | ||
|
|
7e7a8cbc1d | ||
|
|
4f767f4bfe | ||
|
|
63f714ae2f | ||
|
|
1b3b9b707c | ||
|
|
f64bc8a6d4 | ||
|
|
102834130d | ||
|
|
fdc6a11cbc | ||
|
|
19b20f55ce | ||
|
|
60d072ce46 | ||
|
|
34f05b9276 | ||
|
|
1b476b0430 | ||
|
|
b294710e60 | ||
|
|
f8cd325d1b | ||
|
|
2a6c23e173 | ||
|
|
d7768b7221 | ||
|
|
b8821eac57 | ||
|
|
d20b64cf37 | ||
|
|
f0ddd6ca29 | ||
|
|
574d9e09d6 | ||
|
|
7085a50f36 | ||
|
|
0485459da2 | ||
|
|
318439af2e | ||
|
|
4d52ff362f | ||
|
|
14b294c10c | ||
|
|
2758e8d438 | ||
|
|
b5a6b4b945 | ||
|
|
ac94f81b77 | ||
|
|
06747d7dd3 | ||
|
|
fb9b9215e0 | ||
|
|
eed0505f6e | ||
|
|
8f6aa8bcff | ||
|
|
6f9cabbd04 | ||
|
|
355d20faf3 | ||
|
|
15c4a64a81 | ||
|
|
49ec65a735 | ||
|
|
7cdea96caf | ||
|
|
8bf7da3b6b | ||
|
|
c1ad9d1227 | ||
|
|
e2e2b5ddb2 | ||
|
|
b4584dd0b0 | ||
|
|
55e5d178bd | ||
|
|
f778702257 | ||
|
|
b4ff07cfcb | ||
|
|
d43858078f | ||
|
|
f2cf918be5 | ||
|
|
54dd027a64 | ||
|
|
1ea894ab30 | ||
|
|
92c45f4b61 | ||
|
|
03cba8f5bd | ||
|
|
97f08ba0b3 | ||
|
|
c843815c6c | ||
|
|
b5785b3370 | ||
|
|
a6e5a5a619 | ||
|
|
2d627f633b | ||
|
|
ef486764ac | ||
|
|
fce3962376 | ||
|
|
5a40a0ee9c | ||
|
|
4bf795922d | ||
|
|
1646b240c7 | ||
|
|
d4f7bfaa6c | ||
|
|
bac06d2bc7 | ||
|
|
579499d9e8 | ||
|
|
b8c46bfc47 | ||
|
|
d234ce4f63 | ||
|
|
1be807e748 | ||
|
|
f4db2613eb | ||
|
|
bae6098e91 | ||
|
|
c40153fab1 | ||
|
|
e5eec4a5dc | ||
|
|
887bb8c482 | ||
|
|
0642bf5e70 | ||
|
|
513208a117 | ||
|
|
49247f0a83 | ||
|
|
ccb7dd482a | ||
|
|
08f40ff46b | ||
|
|
956f7b5fdf | ||
|
|
40d0f8c401 | ||
|
|
cbc7580fcd | ||
|
|
f96dfd6e8f | ||
|
|
ea24ebaf92 | ||
|
|
504e760760 | ||
|
|
c5e7cfb4f5 | ||
|
|
9904e3a5e8 | ||
|
|
191673b049 | ||
|
|
3a6d11f9b8 | ||
|
|
e022ad3742 | ||
|
|
16d9350992 | ||
|
|
5e1d7b6901 | ||
|
|
82d4cef182 | ||
|
|
5a112ea4bb | ||
|
|
b058e1cadf | ||
|
|
a8b28ef262 | ||
|
|
080f3fb074 | ||
|
|
997f10c7e9 | ||
|
|
4ced4d0933 | ||
|
|
eafe8e327a | ||
|
|
a4c89a3dec | ||
|
|
902390d57a | ||
|
|
5c55590922 | ||
|
|
0485932309 | ||
|
|
e1a3aded4e | ||
|
|
5b2d5c76c8 | ||
|
|
2c3c9e84a5 | ||
|
|
ad90ca6366 | ||
|
|
88952f0ab2 | ||
|
|
29cd54ea8c | ||
|
|
c2ee6da367 | ||
|
|
317801ca5e | ||
|
|
3923da14f7 | ||
|
|
5aa691cc3a | ||
|
|
04712d57f4 | ||
|
|
ed4c861e78 | ||
|
|
587eaa8054 | ||
|
|
78b5ea1f6b | ||
|
|
6412aa3ece | ||
|
|
68a3ba0c41 | ||
|
|
ecaba9efc1 | ||
|
|
fb682944d9 | ||
|
|
9c60e4987c | ||
|
|
59b361fb46 | ||
|
|
f3b2c0a67e | ||
|
|
69c04d5e29 | ||
|
|
78f4115a32 | ||
|
|
9b1b83f5e7 | ||
|
|
bd859e98d3 | ||
|
|
d7accdcf0c | ||
|
|
d159fea7b8 | ||
|
|
b5b91d578d | ||
|
|
498055bc8d | ||
|
|
502169a5ad | ||
|
|
42fbbbd8a6 | ||
|
|
dd0b26de4c | ||
|
|
10665bfaff | ||
|
|
2576ed166f | ||
|
|
9ad7413189 | ||
|
|
9cd405a66f | ||
|
|
fc6773d7d3 | ||
|
|
6abce365c5 |
76
.circleci/config.yml
Normal file
76
.circleci/config.yml
Normal file
@@ -0,0 +1,76 @@
|
||||
version: 2
|
||||
|
||||
jobs:
|
||||
build:
|
||||
environment:
|
||||
- BOOST_LIBRARY=process
|
||||
- CXX_STANDARD=gnu++11
|
||||
docker:
|
||||
- image: gcc:7
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Setting up Environment
|
||||
command: |
|
||||
echo 'export BOOST="$HOME/boost-local"' >> $BASH_ENV
|
||||
if [ $CIRCLE_BRANCH = "master" ]; then
|
||||
echo 'export BOOST_BRANCH="master"' >> $BASH_ENV;
|
||||
else
|
||||
echo 'export BOOST_BRANCH="develop"' >> $BASH_ENV;
|
||||
fi
|
||||
echo 'export BOOST_REMOVE="$BOOST/libs/$BOOST_LIBRARY"' >> $BASH_ENV
|
||||
HOME_SED_=$(echo $HOME | sed -e 's/\//\\\//g')
|
||||
echo 'export HOME_SED=$HOME_SED_' >> $BASH_ENV
|
||||
- run:
|
||||
name: install pre dependencies
|
||||
command: |
|
||||
apt-get update -yqq
|
||||
apt-get install git curl valgrind -y
|
||||
- run:
|
||||
name: Initializing git repo for boost
|
||||
command: |
|
||||
git init $BOOST
|
||||
cd $BOOST
|
||||
echo Testing $BRANCH_TO_TEST
|
||||
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
|
||||
rm -rf $BOOST_REMOVE
|
||||
mv $HOME/project $BOOST_REMOVE
|
||||
- run:
|
||||
name: Bootstrapping boost-build
|
||||
command: |
|
||||
cd $BOOST
|
||||
./bootstrap.sh
|
||||
./b2 headers
|
||||
- run:
|
||||
name: Building examples
|
||||
command: |
|
||||
cd $BOOST_REMOVE/example
|
||||
../../../b2 -j2 address-model=64 architecture=x86 toolset=gcc cxxflags="-std=gnu++14" -sBOOST_BUILD_PATH=. | tee example.log || FAILED=1
|
||||
sed -i -e "s/^..\/..\/..\/boost\/process\//\/root\/project\/include\/boost\/process\//gm" example.log
|
||||
python <(curl -s https://report.ci/annotate.py) --tool gcc --name "Circle CI Gcc Build" --input example.log
|
||||
exit $FAILED
|
||||
- run:
|
||||
name: Running Unit tests
|
||||
command: |
|
||||
cd $BOOST_REMOVE/test
|
||||
../../../b2 -j2 with-valgrind address-model=64 architecture=x86 testing.launcher=valgrind valgrind=on toolset=gcc cxxflags="--coverage -std=$CXX_STANDARD" linkflags="--coverage" -sBOOST_BUILD_PATH=. | tee test.log || FAILED=1
|
||||
../../../b2 -j2 without-valgrind address-model=64 architecture=x86 toolset=gcc cxxflags="--coverage -std=$CXX_STANDARD" linkflags="--coverage" -sBOOST_BUILD_PATH=. | tee no-valgrind.log || FAILED=1
|
||||
sed -i -e "s/^..\/..\/..\/boost\/process\//\/root\/project\/include\/boost\/process\//gm" test.log
|
||||
sed -i -e "s/^..\/..\/..\/boost\/process\//\/root\/project\/include\/boost\/process\//gm" no-valgrind.log
|
||||
|
||||
python <(curl -s https://report.ci/annotate.py) --tool gcc --input test.log
|
||||
python <(curl -s https://report.ci/annotate.py) --tool gcc --input no-valgrind.log
|
||||
python <(curl -s https://report.ci/upload.py) --name "Circle CI Gcc Tests" --framework boost
|
||||
bash <(curl -s https://codecov.io/bash) -x gcov || true
|
||||
echo "BUILD_RESULT: $FAILED"
|
||||
exit $FAILED
|
||||
187
.travis.yml
187
.travis.yml
@@ -10,28 +10,6 @@
|
||||
#
|
||||
# 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
|
||||
@@ -39,81 +17,122 @@ env:
|
||||
sudo: false
|
||||
language: cpp
|
||||
compiler:
|
||||
- gcc
|
||||
- gcc
|
||||
|
||||
os:
|
||||
- linux
|
||||
- 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
|
||||
|
||||
|
||||
|
||||
# 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"
|
||||
# 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
|
||||
|
||||
# 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
|
||||
script:
|
||||
# `--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=.
|
||||
# `--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=.
|
||||
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 "/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 "*.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 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"
|
||||
# ... 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
|
||||
|
||||
# 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"
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
# Sending data to Coveralls
|
||||
- cd $TRAVIS_BUILD_DIR
|
||||
- gem install coveralls-lcov
|
||||
- coveralls-lcov coverals/coverage.info
|
||||
|
||||
@@ -4,10 +4,11 @@ Boost.process is a library for comfortable management of processes, released wit
|
||||
|
||||
### Test results
|
||||
|
||||
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) |
|
||||
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)
|
||||
|
||||
|
||||
[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_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 __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 __async_handler__ [classref boost::process::extend::async_handler ex::async_handler]]
|
||||
[def __get_io_service__ [funcref boost::process::extend::get_io_service ex::get_io_service]]
|
||||
[def __get_io_context__ [funcref boost::process::extend::get_io_context ex::get_io_context]]
|
||||
|
||||
[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", ex::__on_success__=[](auto & exec) {std::cout << "hello world" << std::endl;});
|
||||
__child__ c("foo", __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_service for some reason, the following code will do that.
|
||||
this functionality is also available for extensions. If the class needs the __io_context__ for some reason, the following code will do that.
|
||||
|
||||
```
|
||||
struct async_foo : __handler__, __require_io_service__
|
||||
struct async_foo : __handler__, __require_io_context__
|
||||
{
|
||||
tempalte<typename Executor>
|
||||
void on_setup(Executor & exec)
|
||||
{
|
||||
io_service & ios = __get_io_service__(exec.seq); //gives us a reference and a compiler error if not present.
|
||||
__io_context__ & ios = __get_io_context__(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_service require_io_service] is necessary, so [funcref boost::process::system system] provides one.]
|
||||
[note Inheriting [globalref boost::process::extend::require_io_context require_io_context] 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_service require_io_service] .]
|
||||
[note [globalref boost::process::extend::async_handler async_handler] implies [globalref boost::process::extend::require_io_context require_io_context] .]
|
||||
|
||||
```
|
||||
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;
|
||||
};
|
||||
|
||||
14
filter_section_warning.py
Normal file
14
filter_section_warning.py
Normal file
@@ -0,0 +1,14 @@
|
||||
#!/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,6 +25,7 @@
|
||||
#include <type_traits>
|
||||
#include <memory>
|
||||
#include <boost/asio/async_result.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <tuple>
|
||||
|
||||
@@ -64,11 +65,12 @@ struct async_system_handler : ::boost::process::detail::api::async_handler
|
||||
errored = true;
|
||||
#endif
|
||||
auto & h = init.completion_handler;
|
||||
ios.post(
|
||||
[h, ec]() mutable
|
||||
{
|
||||
h(boost::system::error_code(ec.value(), boost::system::system_category()), -1);
|
||||
});
|
||||
boost::asio::post(
|
||||
ios.get_executor(),
|
||||
[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))
|
||||
|
||||
@@ -92,6 +92,10 @@ 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,6 +101,8 @@ 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;
|
||||
@@ -143,11 +145,12 @@ public:
|
||||
|
||||
bool running(std::error_code & ec) noexcept
|
||||
{
|
||||
if (valid() && !_exited())
|
||||
ec.clear();
|
||||
if (valid() && !_exited() && !ec)
|
||||
{
|
||||
int exit_code = 0;
|
||||
auto res = boost::process::detail::api::is_running(_child_handle, exit_code, ec);
|
||||
if (!res && !_exited())
|
||||
if (!ec && !res && !_exited())
|
||||
_exit_status->store(exit_code);
|
||||
|
||||
return res;
|
||||
@@ -157,10 +160,11 @@ public:
|
||||
|
||||
void terminate(std::error_code & ec) noexcept
|
||||
{
|
||||
if (valid() && running(ec))
|
||||
if (valid() && running(ec) && !ec)
|
||||
boost::process::detail::api::terminate(_child_handle, ec);
|
||||
|
||||
_terminated = true;
|
||||
if (!ec)
|
||||
_terminated = true;
|
||||
}
|
||||
|
||||
void wait(std::error_code & ec) noexcept
|
||||
@@ -169,7 +173,8 @@ public:
|
||||
{
|
||||
int exit_code = 0;
|
||||
boost::process::detail::api::wait(_child_handle, exit_code, ec);
|
||||
_exit_status->store(exit_code);
|
||||
if (!ec)
|
||||
_exit_status->store(exit_code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +191,7 @@ public:
|
||||
{
|
||||
int exit_code = 0;
|
||||
auto b = boost::process::detail::api::wait_until(_child_handle, exit_code, timeout_time, ec);
|
||||
if (!b)
|
||||
if (!b || ec)
|
||||
return false;
|
||||
_exit_status->store(exit_code);
|
||||
}
|
||||
|
||||
@@ -57,6 +57,10 @@ 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;
|
||||
|
||||
@@ -10,11 +10,13 @@
|
||||
|
||||
namespace boost { namespace asio {
|
||||
|
||||
class mutable_buffer;
|
||||
class mutable_buffers_1;
|
||||
template<typename T>
|
||||
struct is_mutable_buffer_sequence;
|
||||
|
||||
template<typename T>
|
||||
struct is_const_buffer_sequence;
|
||||
|
||||
|
||||
class const_buffer;
|
||||
class const_buffers_1;
|
||||
|
||||
template<typename Allocator>
|
||||
class basic_streambuf;
|
||||
@@ -22,6 +24,8 @@ 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;
|
||||
@@ -30,7 +34,9 @@ template <typename SignalSetService>
|
||||
class basic_signal_set;
|
||||
typedef basic_signal_set<signal_set_service> signal_set;
|
||||
#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
|
||||
class signal_set;
|
||||
template <typename Executor>
|
||||
class basic_signal_set;
|
||||
typedef basic_signal_set<executor> signal_set;
|
||||
#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
|
||||
|
||||
template <typename Handler>
|
||||
@@ -45,7 +51,9 @@ template <typename StreamDesscriptorService>
|
||||
class basic_stream_descriptor;
|
||||
typedef basic_stream_descriptor<stream_descriptor_service> stream_descriptor;
|
||||
#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
|
||||
class stream_descriptor;
|
||||
template <typename Executor>
|
||||
class basic_stream_descriptor;
|
||||
typedef basic_stream_descriptor<executor> stream_descriptor;
|
||||
#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
|
||||
|
||||
} //posix
|
||||
|
||||
@@ -41,28 +41,28 @@ struct async_in_buffer : ::boost::process::detail::posix::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,
|
||||
[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&, std::size_t){});
|
||||
|
||||
std::move(*pipe).source().close();
|
||||
std::move(*pipe_).source().close();
|
||||
|
||||
this->pipe = nullptr;
|
||||
}
|
||||
|
||||
@@ -114,30 +114,30 @@ struct async_out_future : ::boost::process::detail::posix::handler_base_ext,
|
||||
template <typename Executor>
|
||||
inline void on_success(Executor &)
|
||||
{
|
||||
auto pipe = this->pipe;
|
||||
auto pipe_ = this->pipe;
|
||||
|
||||
auto buffer = this->buffer;
|
||||
auto promise = this->promise;
|
||||
auto buffer_ = this->buffer;
|
||||
auto promise_ = this->promise;
|
||||
|
||||
boost::asio::async_read(*pipe, *buffer,
|
||||
[pipe, buffer, promise](const boost::system::error_code& ec, std::size_t)
|
||||
boost::asio::async_read(*pipe_, *buffer_,
|
||||
[pipe_, buffer_, promise_](const boost::system::error_code& ec, std::size_t)
|
||||
{
|
||||
if (ec && (ec.value() != ENOENT))
|
||||
{
|
||||
std::error_code e(ec.value(), std::system_category());
|
||||
promise->set_exception(std::make_exception_ptr(process_error(e)));
|
||||
promise_->set_exception(std::make_exception_ptr(process_error(e)));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::istream is (buffer.get());
|
||||
std::istream is (buffer_.get());
|
||||
Type arg;
|
||||
arg.resize(buffer->size());
|
||||
is.read(&*arg.begin(), buffer->size());
|
||||
promise->set_value(std::move(arg));
|
||||
arg.resize(buffer_->size());
|
||||
is.read(&*arg.begin(), buffer_->size());
|
||||
promise_->set_value(std::move(arg));
|
||||
}
|
||||
});
|
||||
|
||||
std::move(*pipe).sink().close();
|
||||
std::move(*pipe_).sink().close();
|
||||
this->pipe = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#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>
|
||||
@@ -109,9 +110,9 @@ public:
|
||||
void async_close()
|
||||
{
|
||||
if (_sink.is_open())
|
||||
_sink.get_io_context(). post([this]{_sink.close();});
|
||||
boost::asio::post(_sink.get_executor(), [this]{_sink.close();});
|
||||
if (_source.is_open())
|
||||
_source.get_io_context().post([this]{_source.close();});
|
||||
boost::asio::post(_source.get_executor(), [this]{_source.close();});
|
||||
}
|
||||
|
||||
template<typename MutableBufferSequence>
|
||||
@@ -218,8 +219,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_io_context()),
|
||||
_sink( const_cast<async_pipe&>(p)._sink.get_io_context())
|
||||
_source(const_cast<async_pipe&>(p)._source.get_executor()),
|
||||
_sink( const_cast<async_pipe&>(p)._sink.get_executor())
|
||||
{
|
||||
|
||||
//cannot get the handle from a const object.
|
||||
|
||||
@@ -22,47 +22,12 @@
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if !defined(__GLIBC__)
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace process { namespace detail { namespace posix {
|
||||
|
||||
inline int execvpe(const char* filename, char * const arg_list[], char* env[])
|
||||
{
|
||||
#if defined(__GLIBC__)
|
||||
return ::execvpe(filename, arg_list, env);
|
||||
#else
|
||||
//use my own implementation
|
||||
std::string fn = filename;
|
||||
if ((fn.find('/') == std::string::npos) && ::access(fn.c_str(), X_OK))
|
||||
{
|
||||
auto e = ::environ;
|
||||
while ((*e != nullptr) && !boost::starts_with(*e, "PATH="))
|
||||
e++;
|
||||
|
||||
if (e != nullptr)
|
||||
{
|
||||
std::vector<std::string> path;
|
||||
boost::split(path, *e, boost::is_any_of(":"));
|
||||
|
||||
for (const std::string & pp : path)
|
||||
{
|
||||
auto p = pp + "/" + filename;
|
||||
if (!::access(p.c_str(), X_OK))
|
||||
{
|
||||
fn = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ::execve(fn.c_str(), arg_list, env);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename Executor>
|
||||
struct on_setup_t
|
||||
{
|
||||
@@ -295,15 +260,41 @@ class executor
|
||||
return;
|
||||
//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));
|
||||
}
|
||||
|
||||
std::string prepare_cmd_style_fn; //buffer
|
||||
|
||||
inline void prepare_cmd_style() //this does what execvpe does - but we execute it in the father process, to avoid allocations.
|
||||
{
|
||||
//use my own implementation
|
||||
prepare_cmd_style_fn = exe;
|
||||
if ((prepare_cmd_style_fn.find('/') == std::string::npos) && ::access(prepare_cmd_style_fn.c_str(), X_OK))
|
||||
{
|
||||
auto e = ::environ;
|
||||
while ((*e != nullptr) && !boost::starts_with(*e, "PATH="))
|
||||
e++;
|
||||
|
||||
if (e != nullptr)
|
||||
{
|
||||
std::vector<std::string> path;
|
||||
boost::split(path, *e, boost::is_any_of(":"));
|
||||
|
||||
for (const std::string & pp : path)
|
||||
{
|
||||
auto p = pp + "/" + exe;
|
||||
if (!::access(p.c_str(), X_OK))
|
||||
{
|
||||
prepare_cmd_style_fn = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exe = prepare_cmd_style_fn.c_str();
|
||||
}
|
||||
|
||||
std::error_code _ec;
|
||||
std::string _msg;
|
||||
@@ -342,6 +333,8 @@ child executor<Sequence>::invoke(boost::mpl::true_, boost::mpl::false_) //ignore
|
||||
boost::fusion::for_each(seq, call_on_setup(*this));
|
||||
if (_ec)
|
||||
return child();
|
||||
if (cmd_style)
|
||||
prepare_cmd_style();
|
||||
|
||||
this->pid = ::fork();
|
||||
if (pid == -1)
|
||||
@@ -353,10 +346,7 @@ child executor<Sequence>::invoke(boost::mpl::true_, boost::mpl::false_) //ignore
|
||||
else if (pid == 0)
|
||||
{
|
||||
boost::fusion::for_each(seq, call_on_exec_setup(*this));
|
||||
if (cmd_style)
|
||||
::boost::process::detail::posix::execvpe(exe, cmd_line, env);
|
||||
else
|
||||
::execve(exe, cmd_line, env);
|
||||
::execve(exe, cmd_line, env);
|
||||
auto ec = boost::process::detail::get_last_error();
|
||||
boost::fusion::for_each(seq, call_on_exec_error(*this, ec));
|
||||
_exit(EXIT_FAILURE);
|
||||
@@ -372,71 +362,85 @@ child executor<Sequence>::invoke(boost::mpl::true_, boost::mpl::false_) //ignore
|
||||
template<typename Sequence>
|
||||
child executor<Sequence>::invoke(boost::mpl::false_, boost::mpl::false_)
|
||||
{
|
||||
int p[2];
|
||||
if (::pipe(p) == -1)
|
||||
{
|
||||
set_error(::boost::process::detail::get_last_error(), "pipe(2) failed");
|
||||
return child();
|
||||
}
|
||||
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");
|
||||
return child();
|
||||
}
|
||||
_ec.clear();
|
||||
boost::fusion::for_each(seq, call_on_setup(*this));
|
||||
struct pipe_guard
|
||||
{
|
||||
int p[2];
|
||||
pipe_guard() : p{-1,-1} {}
|
||||
|
||||
~pipe_guard()
|
||||
{
|
||||
if (p[0] != -1)
|
||||
::close(p[0]);
|
||||
if (p[1] != -1)
|
||||
::close(p[1]);
|
||||
}
|
||||
} p{};
|
||||
|
||||
if (::pipe(p.p) == -1)
|
||||
{
|
||||
set_error(::boost::process::detail::get_last_error(), "pipe(2) failed");
|
||||
return child();
|
||||
}
|
||||
if (::fcntl(p.p[1], F_SETFD, FD_CLOEXEC) == -1)
|
||||
{
|
||||
auto err = ::boost::process::detail::get_last_error();
|
||||
set_error(err, "fcntl(2) failed");//this might throw, so we need to be sure our pipe is safe.
|
||||
return child();
|
||||
}
|
||||
_ec.clear();
|
||||
boost::fusion::for_each(seq, call_on_setup(*this));
|
||||
|
||||
if (_ec)
|
||||
{
|
||||
boost::fusion::for_each(seq, call_on_error(*this, _ec));
|
||||
return child();
|
||||
}
|
||||
|
||||
if (cmd_style)
|
||||
prepare_cmd_style();
|
||||
|
||||
this->pid = ::fork();
|
||||
if (pid == -1)
|
||||
{
|
||||
_ec = boost::process::detail::get_last_error();
|
||||
_msg = "fork() failed";
|
||||
boost::fusion::for_each(seq, call_on_fork_error(*this, _ec));
|
||||
boost::fusion::for_each(seq, call_on_error(*this, _ec));
|
||||
return child();
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
_pipe_sink = p.p[1];
|
||||
::close(p.p[0]);
|
||||
|
||||
boost::fusion::for_each(seq, call_on_exec_setup(*this));
|
||||
::execve(exe, cmd_line, env);
|
||||
_ec = boost::process::detail::get_last_error();
|
||||
_msg = "execve failed";
|
||||
boost::fusion::for_each(seq, call_on_exec_error(*this, _ec));
|
||||
|
||||
_write_error(p.p[1]);
|
||||
::close(p.p[1]);
|
||||
|
||||
_exit(EXIT_FAILURE);
|
||||
return child();
|
||||
}
|
||||
|
||||
::close(p.p[1]);
|
||||
p.p[1] = -1;
|
||||
_read_error(p.p[0]);
|
||||
|
||||
}
|
||||
if (_ec)
|
||||
{
|
||||
boost::fusion::for_each(seq, call_on_error(*this, _ec));
|
||||
return child();
|
||||
}
|
||||
|
||||
this->pid = ::fork();
|
||||
if (pid == -1)
|
||||
{
|
||||
_ec = boost::process::detail::get_last_error();
|
||||
_msg = "fork() failed";
|
||||
boost::fusion::for_each(seq, call_on_fork_error(*this, _ec));
|
||||
boost::fusion::for_each(seq, call_on_error(*this, _ec));
|
||||
|
||||
return child();
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
_pipe_sink = p[1];
|
||||
::close(p[0]);
|
||||
|
||||
boost::fusion::for_each(seq, call_on_exec_setup(*this));
|
||||
if (cmd_style)
|
||||
::boost::process::detail::posix::execvpe(exe, cmd_line, env);
|
||||
else
|
||||
::execve(exe, cmd_line, env);
|
||||
_ec = boost::process::detail::get_last_error();
|
||||
_msg = "execve failed";
|
||||
boost::fusion::for_each(seq, call_on_exec_error(*this, _ec));
|
||||
|
||||
_write_error(p[1]);
|
||||
|
||||
_exit(EXIT_FAILURE);
|
||||
return child();
|
||||
}
|
||||
|
||||
child c(child_handle(pid), exit_status);
|
||||
|
||||
::close(p[1]);
|
||||
_read_error(p[0]);
|
||||
|
||||
if (_ec)
|
||||
{
|
||||
boost::fusion::for_each(seq, call_on_error(*this, _ec));
|
||||
return child();
|
||||
}
|
||||
else
|
||||
boost::fusion::for_each(seq, call_on_success(*this));
|
||||
boost::fusion::for_each(seq, call_on_success(*this));
|
||||
|
||||
if (_ec)
|
||||
{
|
||||
@@ -489,6 +493,8 @@ child executor<Sequence>::invoke(boost::mpl::false_, boost::mpl::true_)
|
||||
return child();
|
||||
}
|
||||
_ec.clear();
|
||||
if (cmd_style)
|
||||
this->prepare_cmd_style();
|
||||
|
||||
this->pid = ::vfork();
|
||||
if (pid == -1)
|
||||
@@ -504,10 +510,7 @@ child executor<Sequence>::invoke(boost::mpl::false_, boost::mpl::true_)
|
||||
{
|
||||
boost::fusion::for_each(seq, call_on_exec_setup(*this));
|
||||
|
||||
if (cmd_style)
|
||||
::boost::process::detail::posix::execvpe(exe, cmd_line, env);
|
||||
else
|
||||
::execve(exe, cmd_line, env);
|
||||
::execve(exe, cmd_line, env);
|
||||
|
||||
_ec = boost::process::detail::get_last_error();
|
||||
_msg = "execve failed";
|
||||
|
||||
@@ -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,6 +79,7 @@ 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<
|
||||
@@ -105,6 +106,15 @@ 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,8 +16,11 @@ 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 = 0x7F;
|
||||
static_assert(!WIFEXITED(still_active) && !WIFSIGNALED(still_active), "Internal Error");
|
||||
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");
|
||||
|
||||
inline bool is_running(int code)
|
||||
{
|
||||
|
||||
@@ -27,7 +27,7 @@ struct on_exit_ : boost::process::detail::posix::async_handler
|
||||
{
|
||||
return handler;
|
||||
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#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>
|
||||
@@ -36,22 +38,34 @@ public:
|
||||
{
|
||||
boost::asio::async_completion<
|
||||
SignalHandler, void(boost::system::error_code)> init{handler};
|
||||
|
||||
auto & h = init.completion_handler;
|
||||
_strand.post(
|
||||
boost::asio::dispatch(
|
||||
_strand,
|
||||
[this, 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);
|
||||
//check if the child actually is running first
|
||||
int status;
|
||||
auto pid_res = ::waitpid(pid, &status, WNOHANG);
|
||||
if (pid_res < 0)
|
||||
h(-1, get_last_error());
|
||||
else if ((pid_res == pid) && (WIFEXITED(status) || WIFSIGNALED(status)))
|
||||
h(status, {}); //successfully exited already
|
||||
else //still running
|
||||
{
|
||||
if (_receivers.empty())
|
||||
_signal_set.async_wait(
|
||||
[this](const boost::system::error_code &ec, int)
|
||||
{
|
||||
boost::asio::dispatch(_strand, [this, ec]{this->_handle_signal(ec);});
|
||||
});
|
||||
_receivers.emplace_back(pid, h);
|
||||
}
|
||||
});
|
||||
|
||||
return init.result.get();
|
||||
}
|
||||
void shutdown_service() override
|
||||
void shutdown() override
|
||||
{
|
||||
_receivers.clear();
|
||||
}
|
||||
@@ -104,7 +118,7 @@ void sigchld_service::_handle_signal(const boost::system::error_code & ec)
|
||||
_signal_set.async_wait(
|
||||
[this](const boost::system::error_code & ec, int)
|
||||
{
|
||||
_strand.post([this, ec]{this->_handle_signal(ec);});
|
||||
boost::asio::post(_strand, [this, ec]{this->_handle_signal(ec);});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,8 +57,8 @@ inline bool wait_until(
|
||||
|
||||
::sigset_t sigset;
|
||||
|
||||
::sigemptyset(&sigset);
|
||||
::sigaddset(&sigset, SIGCHLD);
|
||||
sigemptyset(&sigset);
|
||||
sigaddset(&sigset, SIGCHLD);
|
||||
|
||||
auto get_timespec =
|
||||
[](const Duration & dur)
|
||||
@@ -80,7 +80,7 @@ inline bool wait_until(
|
||||
}
|
||||
|
||||
bool timed_out;
|
||||
|
||||
#if defined(BOOST_POSIX_HAS_SIGTIMEDWAIT)
|
||||
do
|
||||
{
|
||||
auto ts = get_timespec(time_out - Clock::now());
|
||||
@@ -101,6 +101,61 @@ 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();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <system_error>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace boost { namespace process { namespace detail { namespace posix {
|
||||
|
||||
@@ -61,8 +62,9 @@ inline bool wait_until(
|
||||
::sigset_t sigset;
|
||||
::siginfo_t siginfo;
|
||||
|
||||
::sigemptyset(&sigset);
|
||||
::sigaddset(&sigset, SIGCHLD);
|
||||
sigemptyset(&sigset);
|
||||
sigaddset(&sigset, SIGCHLD);
|
||||
|
||||
|
||||
auto get_timespec =
|
||||
[](const Duration & dur)
|
||||
@@ -84,6 +86,7 @@ inline bool wait_until(
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(BOOST_POSIX_HAS_SIGTIMEDWAIT)
|
||||
do
|
||||
{
|
||||
auto ts = get_timespec(time_out - Clock::now());
|
||||
@@ -99,13 +102,64 @@ inline bool wait_until(
|
||||
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 != -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};
|
||||
|
||||
do
|
||||
{
|
||||
int status;
|
||||
if ((::waitpid(timeout_pid, &status, WNOHANG) != 0)
|
||||
&& (WIFEXITED(status) || WIFSIGNALED(status)))
|
||||
ret = ::sigwait(&sigset, nullptr);
|
||||
errno = 0;
|
||||
if ((ret == SIGCHLD) && (old_sig.sa_handler != SIG_DFL) && (old_sig.sa_handler != SIG_IGN))
|
||||
old_sig.sa_handler(ret);
|
||||
|
||||
ret = ::waitpid(-p.grp, &siginfo.si_status, 0); //so in case it exited, we wanna reap it first
|
||||
if (ret == -1)
|
||||
{
|
||||
ec = get_last_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
//check if we're done
|
||||
ret = ::waitid(P_PGID, p.grp, &siginfo, WEXITED | WNOHANG);
|
||||
|
||||
}
|
||||
while (((ret != -1) || (errno != ECHILD)) && !(timed_out = (Clock::now() > time_out)));
|
||||
|
||||
#endif
|
||||
|
||||
if (errno != ECHILD)
|
||||
{
|
||||
ec = boost::process::detail::get_last_error();
|
||||
|
||||
@@ -10,10 +10,12 @@
|
||||
|
||||
namespace boost { namespace asio {
|
||||
|
||||
class mutable_buffer;
|
||||
class mutable_buffers_1;
|
||||
class const_buffer;
|
||||
class const_buffers_1;
|
||||
template<typename T>
|
||||
struct is_mutable_buffer_sequence;
|
||||
|
||||
template<typename T>
|
||||
struct is_const_buffer_sequence;
|
||||
|
||||
|
||||
template<typename Allocator>
|
||||
class basic_streambuf;
|
||||
@@ -21,6 +23,9 @@ class basic_streambuf;
|
||||
typedef basic_streambuf<std::allocator<char>> streambuf;
|
||||
class io_context;
|
||||
|
||||
class executor;
|
||||
|
||||
|
||||
template <typename Handler>
|
||||
class basic_yield_context;
|
||||
|
||||
@@ -34,7 +39,10 @@ class basic_stream_handle;
|
||||
|
||||
typedef basic_stream_handle<stream_handle_service> stream_handle;
|
||||
#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
|
||||
class stream_handle;
|
||||
template <typename Executor>
|
||||
class basic_stream_handle;
|
||||
typedef basic_stream_handle<executor> stream_handle;
|
||||
|
||||
#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
|
||||
|
||||
|
||||
@@ -46,7 +54,9 @@ class basic_object_handle;
|
||||
|
||||
typedef basic_object_handle<object_handle_service> object_handle;
|
||||
#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
|
||||
class object_handle;
|
||||
template <typename Executor>
|
||||
class basic_object_handle;
|
||||
typedef basic_object_handle<executor> 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,6 +14,7 @@
|
||||
#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>
|
||||
@@ -54,8 +55,6 @@ public:
|
||||
inline async_pipe(const async_pipe& rhs);
|
||||
async_pipe(async_pipe&& rhs) : _source(std::move(rhs._source)), _sink(std::move(rhs._sink))
|
||||
{
|
||||
rhs._source.assign (::boost::winapi::INVALID_HANDLE_VALUE_);
|
||||
rhs._sink .assign (::boost::winapi::INVALID_HANDLE_VALUE_);
|
||||
}
|
||||
template<class CharT, class Traits = std::char_traits<CharT>>
|
||||
explicit async_pipe(::boost::asio::io_context & ios_source,
|
||||
@@ -99,12 +98,12 @@ public:
|
||||
if (_sink.is_open())
|
||||
{
|
||||
_sink.close();
|
||||
_sink = handle_type(_sink.get_io_context());
|
||||
_sink = handle_type(_sink.get_executor());
|
||||
}
|
||||
if (_source.is_open())
|
||||
{
|
||||
_source.close();
|
||||
_source = handle_type(_source.get_io_context());
|
||||
_source = handle_type(_source.get_executor());
|
||||
}
|
||||
}
|
||||
void close(boost::system::error_code & ec)
|
||||
@@ -112,12 +111,12 @@ public:
|
||||
if (_sink.is_open())
|
||||
{
|
||||
_sink.close(ec);
|
||||
_sink = handle_type(_sink.get_io_context());
|
||||
_sink = handle_type(_sink.get_executor());
|
||||
}
|
||||
if (_source.is_open())
|
||||
{
|
||||
_source.close(ec);
|
||||
_source = handle_type(_source.get_io_context());
|
||||
_source = handle_type(_source.get_executor());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,9 +127,9 @@ public:
|
||||
void async_close()
|
||||
{
|
||||
if (_sink.is_open())
|
||||
_sink.get_io_context(). post([this]{_sink.close();});
|
||||
boost::asio::post(_sink.get_executor(), [this]{_sink.close();});
|
||||
if (_source.is_open())
|
||||
_source.get_io_context().post([this]{_source.close();});
|
||||
boost::asio::post(_source.get_executor(), [this]{_source.close();});
|
||||
}
|
||||
|
||||
template<typename MutableBufferSequence>
|
||||
@@ -189,14 +188,16 @@ public:
|
||||
|
||||
handle_type source(::boost::asio::io_context& ios) &&
|
||||
{
|
||||
::boost::asio::windows::stream_handle stolen(ios, _source.native_handle());
|
||||
_source.assign(::boost::winapi::INVALID_HANDLE_VALUE_);
|
||||
::boost::asio::windows::stream_handle stolen(ios.get_executor(), _source.native_handle());
|
||||
boost::system::error_code ec;
|
||||
_source.assign(::boost::winapi::INVALID_HANDLE_VALUE_, ec);
|
||||
return stolen;
|
||||
}
|
||||
handle_type sink (::boost::asio::io_context& ios) &&
|
||||
{
|
||||
::boost::asio::windows::stream_handle stolen(ios, _sink.native_handle());
|
||||
_sink.assign(::boost::winapi::INVALID_HANDLE_VALUE_);
|
||||
::boost::asio::windows::stream_handle stolen(ios.get_executor(), _sink.native_handle());
|
||||
boost::system::error_code ec;
|
||||
_sink.assign(::boost::winapi::INVALID_HANDLE_VALUE_, ec);
|
||||
return stolen;
|
||||
}
|
||||
|
||||
@@ -214,7 +215,7 @@ public:
|
||||
::boost::winapi::DUPLICATE_SAME_ACCESS_))
|
||||
throw_last_error("Duplicate Pipe Failed");
|
||||
|
||||
return ::boost::asio::windows::stream_handle(ios, source);
|
||||
return ::boost::asio::windows::stream_handle(ios.get_executor(), source);
|
||||
}
|
||||
handle_type sink (::boost::asio::io_context& ios) const &
|
||||
{
|
||||
@@ -230,16 +231,15 @@ public:
|
||||
::boost::winapi::DUPLICATE_SAME_ACCESS_))
|
||||
throw_last_error("Duplicate Pipe Failed");
|
||||
|
||||
return ::boost::asio::windows::stream_handle(ios, sink);
|
||||
return ::boost::asio::windows::stream_handle(ios.get_executor(), sink);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
async_pipe::async_pipe(const async_pipe& p) :
|
||||
_source(const_cast<handle_type&>(p._source).get_io_context()),
|
||||
_sink (const_cast<handle_type&>(p._sink).get_io_context())
|
||||
_source(const_cast<handle_type&>(p._source).get_executor()),
|
||||
_sink (const_cast<handle_type&>(p._sink).get_executor())
|
||||
{
|
||||
|
||||
auto proc = ::boost::winapi::GetCurrentProcess();
|
||||
|
||||
::boost::winapi::HANDLE_ source;
|
||||
@@ -265,8 +265,10 @@ async_pipe::async_pipe(const async_pipe& p) :
|
||||
::boost::winapi::DUPLICATE_SAME_ACCESS_))
|
||||
throw_last_error("Duplicate Pipe Failed");
|
||||
|
||||
_source.assign(source);
|
||||
_sink. assign(sink);
|
||||
if (source != ::boost::winapi::INVALID_HANDLE_VALUE_)
|
||||
_source.assign(source);
|
||||
if (sink != ::boost::winapi::INVALID_HANDLE_VALUE_)
|
||||
_sink. assign(sink);
|
||||
}
|
||||
|
||||
|
||||
@@ -309,6 +311,44 @@ async_pipe::async_pipe(boost::asio::io_context & ios_source,
|
||||
_sink.assign(sink);
|
||||
}
|
||||
|
||||
template<class CharT, class Traits>
|
||||
async_pipe& async_pipe::operator=(const basic_pipe<CharT, Traits> & p)
|
||||
{
|
||||
auto proc = ::boost::winapi::GetCurrentProcess();
|
||||
|
||||
::boost::winapi::HANDLE_ source;
|
||||
::boost::winapi::HANDLE_ sink;
|
||||
|
||||
//cannot get the handle from a const object.
|
||||
auto source_in = p.native_source();
|
||||
auto sink_in = p.native_sink();
|
||||
|
||||
if (source_in == ::boost::winapi::INVALID_HANDLE_VALUE_)
|
||||
source = ::boost::winapi::INVALID_HANDLE_VALUE_;
|
||||
else if (!::boost::winapi::DuplicateHandle(
|
||||
proc, source_in.native_handle(), proc, &source, 0,
|
||||
static_cast<::boost::winapi::BOOL_>(true),
|
||||
::boost::winapi::DUPLICATE_SAME_ACCESS_))
|
||||
throw_last_error("Duplicate Pipe Failed");
|
||||
|
||||
if (sink_in == ::boost::winapi::INVALID_HANDLE_VALUE_)
|
||||
sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
|
||||
else if (!::boost::winapi::DuplicateHandle(
|
||||
proc, sink_in.native_handle(), proc, &sink, 0,
|
||||
static_cast<::boost::winapi::BOOL_>(true),
|
||||
::boost::winapi::DUPLICATE_SAME_ACCESS_))
|
||||
throw_last_error("Duplicate Pipe Failed");
|
||||
|
||||
//so we also assign the io_context
|
||||
if (source != ::boost::winapi::INVALID_HANDLE_VALUE_)
|
||||
_source.assign(source);
|
||||
|
||||
if (sink != ::boost::winapi::INVALID_HANDLE_VALUE_)
|
||||
_sink.assign(sink);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
async_pipe& async_pipe::operator=(const async_pipe & p)
|
||||
{
|
||||
auto proc = ::boost::winapi::GetCurrentProcess();
|
||||
@@ -320,6 +360,8 @@ async_pipe& async_pipe::operator=(const async_pipe & p)
|
||||
auto &source_in = const_cast<::boost::asio::windows::stream_handle &>(p._source);
|
||||
auto &sink_in = const_cast<::boost::asio::windows::stream_handle &>(p._sink);
|
||||
|
||||
source_in.get_executor();
|
||||
|
||||
if (source_in.native_handle() == ::boost::winapi::INVALID_HANDLE_VALUE_)
|
||||
source = ::boost::winapi::INVALID_HANDLE_VALUE_;
|
||||
else if (!::boost::winapi::DuplicateHandle(
|
||||
@@ -337,24 +379,23 @@ 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_io_context(), source);
|
||||
_sink = ::boost::asio::windows::stream_handle(source_in.get_io_context(), sink);
|
||||
if (source != ::boost::winapi::INVALID_HANDLE_VALUE_)
|
||||
_source = ::boost::asio::windows::stream_handle(source_in.get_executor(), source);
|
||||
else
|
||||
_source = ::boost::asio::windows::stream_handle(source_in.get_executor());
|
||||
|
||||
if (sink != ::boost::winapi::INVALID_HANDLE_VALUE_)
|
||||
_sink = ::boost::asio::windows::stream_handle(source_in.get_executor(), sink);
|
||||
else
|
||||
_sink = ::boost::asio::windows::stream_handle(source_in.get_executor());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
async_pipe& async_pipe::operator=(async_pipe && rhs)
|
||||
{
|
||||
if (_source.native_handle() != ::boost::winapi::INVALID_HANDLE_VALUE_)
|
||||
::boost::winapi::CloseHandle(_source.native_handle());
|
||||
|
||||
if (_sink.native_handle() != ::boost::winapi::INVALID_HANDLE_VALUE_)
|
||||
::boost::winapi::CloseHandle(_sink.native_handle());
|
||||
|
||||
_source.assign(rhs._source.native_handle());
|
||||
_sink .assign(rhs._sink .native_handle());
|
||||
rhs._source.assign(::boost::winapi::INVALID_HANDLE_VALUE_);
|
||||
rhs._sink .assign(::boost::winapi::INVALID_HANDLE_VALUE_);
|
||||
_source = std::move(rhs._source);
|
||||
_sink = std::move(rhs._sink);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -143,8 +143,13 @@ 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);
|
||||
|
||||
@@ -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_SERVICE_REF_HPP_
|
||||
#define BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_
|
||||
#ifndef BOOST_PROCESS_WINDOWS_IO_CONTEXT_REF_HPP_
|
||||
#define BOOST_PROCESS_WINDOWS_IO_CONTEXT_REF_HPP_
|
||||
|
||||
#include <boost/process/detail/handler_base.hpp>
|
||||
#include <boost/process/detail/windows/async_handler.hpp>
|
||||
@@ -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, handle)),
|
||||
handle(new boost::asio::windows::object_handle(ios.get_executor(), handle)),
|
||||
exit_status(exit_status)
|
||||
{
|
||||
|
||||
@@ -157,4 +157,4 @@ private:
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /* BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_ */
|
||||
#endif /* BOOST_PROCESS_WINDOWS_IO_CONTEXT_REF_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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace boost { namespace process { namespace detail { namespace windows {
|
||||
struct group_handle;
|
||||
|
||||
|
||||
inline bool wait_impl(const group_handle & p, std::error_code & ec, int wait_time)
|
||||
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;
|
||||
@@ -48,11 +48,11 @@ inline bool wait_impl(const group_handle & p, std::error_code & ec, int wait_tim
|
||||
return false; //correct, nothing left.
|
||||
}
|
||||
//reduce the remaining wait time -> in case interrupted by something else
|
||||
if (wait_time != ::boost::winapi::infinite)
|
||||
if (wait_time != static_cast<int>(::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();
|
||||
wait_time -= static_cast<std::chrono::system_clock::rep>(diff.count());
|
||||
start_time = now;
|
||||
if (wait_time <= 0)
|
||||
return true; //timeout with other source
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -122,20 +122,6 @@ system("b2", std_out > null);
|
||||
|
||||
namespace boost { namespace process { namespace detail {
|
||||
|
||||
|
||||
template<typename T> using is_streambuf = typename std::is_same<T, boost::asio::streambuf>::type;
|
||||
template<typename T> using is_const_buffer =
|
||||
std::integral_constant<bool,
|
||||
std::is_same< boost::asio::const_buffer, T>::value |
|
||||
std::is_base_of<boost::asio::const_buffer, T>::value
|
||||
>;
|
||||
template<typename T> using is_mutable_buffer =
|
||||
std::integral_constant<bool,
|
||||
std::is_same< boost::asio::mutable_buffer, T>::value |
|
||||
std::is_base_of<boost::asio::mutable_buffer, T>::value
|
||||
>;
|
||||
|
||||
|
||||
struct null_t {constexpr null_t() {}};
|
||||
struct close_t;
|
||||
|
||||
@@ -177,19 +163,25 @@ struct std_in_
|
||||
api::async_pipe_in operator=(async_pipe & p) const {return p;}
|
||||
api::async_pipe_in operator<(async_pipe & p) const {return p;}
|
||||
|
||||
template<typename T, typename = typename std::enable_if<
|
||||
is_const_buffer<T>::value || is_mutable_buffer<T>::value
|
||||
>::type>
|
||||
api::async_in_buffer<const T> operator=(const T & buf) const {return buf;}
|
||||
template<typename T, typename = typename std::enable_if<is_streambuf<T>::value>::type >
|
||||
api::async_in_buffer<T> operator=(T & buf) const {return buf;}
|
||||
template<typename T>
|
||||
auto operator=(const T & buf) const -> typename std::enable_if<asio::is_const_buffer_sequence<T>::value, api::async_in_buffer<const T>>::type {return buf;}
|
||||
template<typename T>
|
||||
auto operator<(const T & buf) const -> typename std::enable_if<asio::is_const_buffer_sequence<T>::value, api::async_in_buffer<const T>>::type {return buf;}
|
||||
|
||||
template<typename T, typename = typename std::enable_if<
|
||||
is_const_buffer<T>::value || is_mutable_buffer<T>::value
|
||||
>::type>
|
||||
api::async_in_buffer<const T> operator<(const T & buf) const {return buf;}
|
||||
template<typename T, typename = typename std::enable_if<is_streambuf<T>::value>::type >
|
||||
api::async_in_buffer<T> operator<(T & buf) const {return buf;}
|
||||
template<typename T>
|
||||
auto operator=(T & buf) const -> typename std::enable_if<asio::is_const_buffer_sequence<T>::value, api::async_in_buffer<T>>::type {return buf;}
|
||||
template<typename T>
|
||||
auto operator<(T & buf) const -> typename std::enable_if<asio::is_const_buffer_sequence<T>::value, api::async_in_buffer<T>>::type {return buf;}
|
||||
|
||||
template<typename Allocator>
|
||||
api::async_in_buffer<asio::basic_streambuf<Allocator>> operator<(boost::asio::basic_streambuf<Allocator> & p) const {return p;}
|
||||
template<typename Allocator>
|
||||
api::async_in_buffer<asio::basic_streambuf<Allocator>> operator=(boost::asio::basic_streambuf<Allocator> & p) const {return p;}
|
||||
|
||||
template<typename Allocator>
|
||||
api::async_in_buffer<asio::basic_streambuf<Allocator>> operator<(const boost::asio::basic_streambuf<Allocator> & p) const {return p;}
|
||||
template<typename Allocator>
|
||||
api::async_in_buffer<asio::basic_streambuf<Allocator>> operator=(const boost::asio::basic_streambuf<Allocator> & p) const {return p;}
|
||||
|
||||
};
|
||||
|
||||
@@ -234,13 +226,24 @@ struct std_out_
|
||||
api::async_pipe_out<p1, p2> operator=(async_pipe & p) const {return p;}
|
||||
api::async_pipe_out<p1, p2> operator>(async_pipe & p) const {return p;}
|
||||
|
||||
api::async_out_buffer<p1, p2, const asio::mutable_buffer> operator=(const asio::mutable_buffer & buf) const {return buf;}
|
||||
api::async_out_buffer<p1, p2, const asio::mutable_buffers_1> operator=(const asio::mutable_buffers_1 & buf) const {return buf;}
|
||||
api::async_out_buffer<p1, p2, asio::streambuf> operator=(asio::streambuf & os) const {return os ;}
|
||||
template<typename Allocator>
|
||||
api::async_out_buffer<p1, p2, asio::basic_streambuf<Allocator>> operator=(boost::asio::basic_streambuf<Allocator> & p) const {return p;}
|
||||
template<typename Allocator>
|
||||
api::async_out_buffer<p1, p2, asio::basic_streambuf<Allocator>> operator>(boost::asio::basic_streambuf<Allocator> & p) const {return p;}
|
||||
|
||||
api::async_out_buffer<p1, p2, const asio::mutable_buffer> operator>(const asio::mutable_buffer & buf) const {return buf;}
|
||||
api::async_out_buffer<p1, p2, const asio::mutable_buffers_1> operator>(const asio::mutable_buffers_1 & buf) const {return buf;}
|
||||
api::async_out_buffer<p1, p2, asio::streambuf> operator>(asio::streambuf & os) const {return os ;}
|
||||
template<typename Buffer>
|
||||
auto operator=(const Buffer & buf) const
|
||||
-> typename std::enable_if<asio::is_mutable_buffer_sequence<Buffer>::value, api::async_out_buffer<p1, p2, Buffer>>::type
|
||||
{
|
||||
return buf;
|
||||
}
|
||||
|
||||
template<typename Buffer>
|
||||
auto operator>(const Buffer & buf) const
|
||||
-> typename std::enable_if<asio::is_mutable_buffer_sequence<Buffer>::value, api::async_out_buffer<p1, p2, Buffer>>::type
|
||||
{
|
||||
return buf;
|
||||
}
|
||||
|
||||
api::async_out_future<p1,p2, std::string> operator=(std::future<std::string> & fut) const { return fut;}
|
||||
api::async_out_future<p1,p2, std::string> operator>(std::future<std::string> & fut) const { return fut;}
|
||||
|
||||
@@ -223,7 +223,7 @@ private:
|
||||
return false;
|
||||
|
||||
auto base = this->pbase();
|
||||
auto wrt = _pipe.write(base,
|
||||
std::ptrdiff_t 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>
|
||||
{
|
||||
basic_pipebuf<CharT, Traits> _buf;
|
||||
mutable 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() {return &_buf;};
|
||||
basic_pipebuf<CharT, Traits>* rdbuf() const {return &_buf;};
|
||||
|
||||
///Default constructor.
|
||||
basic_ipstream() : std::basic_istream<CharT, Traits>(nullptr)
|
||||
@@ -272,7 +272,10 @@ public:
|
||||
///Copy constructor.
|
||||
basic_ipstream(const basic_ipstream & ) = delete;
|
||||
///Move constructor.
|
||||
basic_ipstream(basic_ipstream && ) = default;
|
||||
basic_ipstream(basic_ipstream && lhs) : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf))
|
||||
{
|
||||
std::basic_istream<CharT, Traits>::rdbuf(&_buf);
|
||||
}
|
||||
|
||||
///Move construct from a pipe.
|
||||
basic_ipstream(pipe_type && p) : std::basic_istream<CharT, Traits>(nullptr), _buf(std::move(p))
|
||||
@@ -289,7 +292,12 @@ public:
|
||||
///Copy assignment.
|
||||
basic_ipstream& operator=(const basic_ipstream & ) = delete;
|
||||
///Move assignment
|
||||
basic_ipstream& operator=(basic_ipstream && ) = default;
|
||||
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);
|
||||
};
|
||||
///Move assignment of a pipe.
|
||||
basic_ipstream& operator=(pipe_type && p)
|
||||
{
|
||||
@@ -326,7 +334,7 @@ template<
|
||||
>
|
||||
class basic_opstream : public std::basic_ostream<CharT, Traits>
|
||||
{
|
||||
basic_pipebuf<CharT, Traits> _buf;
|
||||
mutable basic_pipebuf<CharT, Traits> _buf;
|
||||
public:
|
||||
typedef basic_pipe<CharT, Traits> pipe_type;
|
||||
|
||||
@@ -338,7 +346,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)
|
||||
@@ -348,8 +356,10 @@ public:
|
||||
///Copy constructor.
|
||||
basic_opstream(const basic_opstream & ) = delete;
|
||||
///Move constructor.
|
||||
basic_opstream(basic_opstream && ) = default;
|
||||
|
||||
basic_opstream(basic_opstream && lhs) : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf))
|
||||
{
|
||||
std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
|
||||
}
|
||||
///Move construct from a pipe.
|
||||
basic_opstream(pipe_type && p) : std::basic_ostream<CharT, Traits>(nullptr), _buf(std::move(p))
|
||||
{
|
||||
@@ -363,7 +373,13 @@ public:
|
||||
///Copy assignment.
|
||||
basic_opstream& operator=(const basic_opstream & ) = delete;
|
||||
///Move assignment
|
||||
basic_opstream& operator=(basic_opstream && ) = default;
|
||||
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);
|
||||
};
|
||||
|
||||
///Move assignment of a pipe.
|
||||
basic_opstream& operator=(pipe_type && p)
|
||||
{
|
||||
@@ -401,7 +417,7 @@ template<
|
||||
>
|
||||
class basic_pstream : public std::basic_iostream<CharT, Traits>
|
||||
{
|
||||
basic_pipebuf<CharT, Traits> _buf;
|
||||
mutable basic_pipebuf<CharT, Traits> _buf;
|
||||
public:
|
||||
typedef basic_pipe<CharT, Traits> pipe_type;
|
||||
|
||||
@@ -413,7 +429,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)
|
||||
@@ -423,8 +439,10 @@ public:
|
||||
///Copy constructor.
|
||||
basic_pstream(const basic_pstream & ) = delete;
|
||||
///Move constructor.
|
||||
basic_pstream(basic_pstream && ) = default;
|
||||
|
||||
basic_pstream(basic_pstream && lhs) : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(lhs._buf))
|
||||
{
|
||||
std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
|
||||
}
|
||||
///Move construct from a pipe.
|
||||
basic_pstream(pipe_type && p) : std::basic_iostream<CharT, Traits>(nullptr), _buf(std::move(p))
|
||||
{
|
||||
@@ -438,7 +456,12 @@ public:
|
||||
///Copy assignment.
|
||||
basic_pstream& operator=(const basic_pstream & ) = delete;
|
||||
///Move assignment
|
||||
basic_pstream& operator=(basic_pstream && ) = default;
|
||||
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);
|
||||
};
|
||||
///Move assignment of a pipe.
|
||||
basic_pstream& operator=(pipe_type && p)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#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,6 +22,7 @@
|
||||
#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>
|
||||
@@ -62,7 +63,7 @@ inline int system_impl(
|
||||
::boost::process::on_exit(
|
||||
[&](int, const std::error_code&)
|
||||
{
|
||||
ios.post([&]{exited.store(true);});
|
||||
boost::asio::post(ios.get_executor(), [&]{exited.store(true);});
|
||||
}));
|
||||
if (!c.valid() || !check.succeeded)
|
||||
return -1;
|
||||
|
||||
105
test/Jamfile.jam
105
test/Jamfile.jam
@@ -19,6 +19,7 @@ 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
|
||||
@@ -52,65 +53,73 @@ 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 -- ;
|
||||
#return --log_level=error --report_level=detailed -- ;
|
||||
}
|
||||
|
||||
|
||||
test-suite bare :
|
||||
[ run environment.cpp system filesystem ]
|
||||
[ run async_pipe.cpp system filesystem ]
|
||||
[ run pipe.cpp system filesystem ]
|
||||
[ 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 ] ]
|
||||
[ compile no_ansi_apps.cpp ]
|
||||
[ compile-fail spawn_fail.cpp ]
|
||||
[ compile-fail async_system_fail.cpp ]
|
||||
[ compile asio_no_deprecated.cpp ]
|
||||
;
|
||||
|
||||
test-suite with-valgrind :
|
||||
[ 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 group.cpp system thread filesystem : : 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 : : sparring_partner ]
|
||||
[ 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 run_exe.cpp filesystem : : sparring_partner ]
|
||||
[ 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 ]
|
||||
[ 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 ]
|
||||
: <dependency>bare ;
|
||||
|
||||
test-suite without-valgrind :
|
||||
[ 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 ]
|
||||
[ 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 ]
|
||||
;
|
||||
|
||||
|
||||
|
||||
@@ -17,12 +17,13 @@ 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.61.{build}-{branch}
|
||||
version: 1.69.{build}-{branch}
|
||||
|
||||
# branches to build
|
||||
branches:
|
||||
@@ -72,3 +73,5 @@ 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>
|
||||
#else
|
||||
#include <boost/process/windows.hpp>
|
||||
#endif
|
||||
164
test/async.cpp
164
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,15 +20,21 @@
|
||||
#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;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(2))
|
||||
#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))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
using namespace boost::asio;
|
||||
@@ -39,34 +45,34 @@ BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(2))
|
||||
|
||||
bool exit_called_for_c1 = false;
|
||||
int exit_code_c1 = 0;
|
||||
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::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();
|
||||
}));
|
||||
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();
|
||||
@@ -80,7 +86,7 @@ BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(2))
|
||||
BOOST_CHECK_EQUAL(c2.exit_code(), 21);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_wait_sync_wait, *boost::unit_test::timeout(3))
|
||||
BOOST_AUTO_TEST_CASE(async_wait_sync_wait, *boost::unit_test::timeout(5))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
using namespace boost::asio;
|
||||
@@ -90,6 +96,10 @@ BOOST_AUTO_TEST_CASE(async_wait_sync_wait, *boost::unit_test::timeout(3))
|
||||
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",
|
||||
@@ -106,6 +116,7 @@ BOOST_AUTO_TEST_CASE(async_wait_sync_wait, *boost::unit_test::timeout(3))
|
||||
{
|
||||
exit_code = exit; exit_called=true;
|
||||
BOOST_CHECK(!ec_in);
|
||||
timeout.cancel();
|
||||
})
|
||||
);
|
||||
BOOST_REQUIRE(!ec);
|
||||
@@ -121,7 +132,7 @@ BOOST_AUTO_TEST_CASE(async_wait_sync_wait, *boost::unit_test::timeout(3))
|
||||
BOOST_CHECK_EQUAL(c2.exit_code(), 2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_wait_different_contexts, *boost::unit_test::timeout(3))
|
||||
BOOST_AUTO_TEST_CASE(async_wait_different_contexts, *boost::unit_test::timeout(10))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
using namespace boost::asio;
|
||||
@@ -129,6 +140,11 @@ BOOST_AUTO_TEST_CASE(async_wait_different_contexts, *boost::unit_test::timeout(3
|
||||
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;
|
||||
@@ -143,6 +159,7 @@ BOOST_AUTO_TEST_CASE(async_wait_different_contexts, *boost::unit_test::timeout(3
|
||||
BOOST_CHECK(!exit_called_for_c1);
|
||||
exit_code_c1 = exit; exit_called_for_c1=true;
|
||||
BOOST_CHECK(!ec_in);
|
||||
timeout1.cancel();
|
||||
})
|
||||
);
|
||||
BOOST_REQUIRE(!ec);
|
||||
@@ -151,7 +168,7 @@ BOOST_AUTO_TEST_CASE(async_wait_different_contexts, *boost::unit_test::timeout(3
|
||||
int exit_code_c2 = 0;
|
||||
bp::child c2(
|
||||
master_test_suite().argv[1],
|
||||
"test", "--exit-code", "2", "--wait", "1",
|
||||
"test", "--exit-code", "2", "--wait", "4",
|
||||
ec,
|
||||
io_context2,
|
||||
bp::on_exit([&](int exit, const std::error_code& ec_in)
|
||||
@@ -159,13 +176,17 @@ BOOST_AUTO_TEST_CASE(async_wait_different_contexts, *boost::unit_test::timeout(3
|
||||
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
|
||||
io_context2.run();
|
||||
io_context1.run();
|
||||
std::thread thr1{[&]{io_context1.run();}};
|
||||
std::thread thr2{[&]{io_context2.run();}};
|
||||
|
||||
thr1.join();
|
||||
thr2.join();
|
||||
c1.wait(ec);
|
||||
BOOST_REQUIRE(!ec);
|
||||
|
||||
@@ -177,7 +198,7 @@ BOOST_AUTO_TEST_CASE(async_wait_different_contexts, *boost::unit_test::timeout(3
|
||||
BOOST_CHECK_EQUAL(c2.exit_code(), 2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_wait_abort, *boost::unit_test::timeout(2))
|
||||
BOOST_AUTO_TEST_CASE(async_wait_abort, *boost::unit_test::timeout(5))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
using namespace boost::asio;
|
||||
@@ -186,6 +207,9 @@ BOOST_AUTO_TEST_CASE(async_wait_abort, *boost::unit_test::timeout(2))
|
||||
|
||||
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(
|
||||
@@ -196,9 +220,11 @@ BOOST_AUTO_TEST_CASE(async_wait_abort, *boost::unit_test::timeout(2))
|
||||
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);
|
||||
@@ -206,18 +232,21 @@ BOOST_AUTO_TEST_CASE(async_wait_abort, *boost::unit_test::timeout(2))
|
||||
io_context.run();
|
||||
|
||||
BOOST_CHECK(exit_called);
|
||||
BOOST_CHECK(exit_code != 0);
|
||||
BOOST_CHECK_NE(exit_code, 0);
|
||||
BOOST_CHECK_EQUAL(c.exit_code(), exit_code);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_future, *boost::unit_test::timeout(2))
|
||||
BOOST_AUTO_TEST_CASE(async_future, *boost::unit_test::timeout(3))
|
||||
{
|
||||
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(
|
||||
@@ -229,13 +258,15 @@ BOOST_AUTO_TEST_CASE(async_future, *boost::unit_test::timeout(2))
|
||||
);
|
||||
|
||||
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(2))
|
||||
BOOST_AUTO_TEST_CASE(async_out_stream, *boost::unit_test::timeout(5))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
@@ -246,6 +277,9 @@ BOOST_AUTO_TEST_CASE(async_out_stream, *boost::unit_test::timeout(2))
|
||||
|
||||
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,
|
||||
@@ -253,8 +287,8 @@ BOOST_AUTO_TEST_CASE(async_out_stream, *boost::unit_test::timeout(2))
|
||||
ec);
|
||||
BOOST_REQUIRE(!ec);
|
||||
|
||||
|
||||
io_context.run();
|
||||
|
||||
std::istream istr(&buf);
|
||||
|
||||
std::string line;
|
||||
@@ -266,7 +300,7 @@ BOOST_AUTO_TEST_CASE(async_out_stream, *boost::unit_test::timeout(2))
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_in_stream, *boost::unit_test::timeout(2))
|
||||
BOOST_AUTO_TEST_CASE(async_in_stream, *boost::unit_test::timeout(5))
|
||||
{
|
||||
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
@@ -283,6 +317,9 @@ BOOST_AUTO_TEST_CASE(async_in_stream, *boost::unit_test::timeout(2))
|
||||
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",
|
||||
@@ -293,8 +330,8 @@ BOOST_AUTO_TEST_CASE(async_in_stream, *boost::unit_test::timeout(2))
|
||||
);
|
||||
BOOST_REQUIRE(!ec);
|
||||
|
||||
|
||||
io_context.run();
|
||||
|
||||
std::istream istr(&buf);
|
||||
|
||||
std::string line;
|
||||
@@ -310,13 +347,16 @@ BOOST_AUTO_TEST_CASE(async_in_stream, *boost::unit_test::timeout(2))
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_error, *boost::unit_test::timeout(2))
|
||||
BOOST_AUTO_TEST_CASE(async_error, *boost::unit_test::timeout(3))
|
||||
{
|
||||
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(
|
||||
@@ -330,7 +370,47 @@ BOOST_AUTO_TEST_CASE(async_error, *boost::unit_test::timeout(2))
|
||||
);
|
||||
|
||||
BOOST_REQUIRE(ec);
|
||||
|
||||
io_context.run();
|
||||
|
||||
BOOST_CHECK(!exit_called);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
BOOST_AUTO_TEST_CASE(mixed_async, *boost::unit_test::timeout(5))
|
||||
{
|
||||
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(master_test_suite().argv[1],
|
||||
"--wait", "1", "--exit-code", "42",
|
||||
ec,
|
||||
io_context,
|
||||
bp::on_exit([&](int exit, const std::error_code& ec_in)
|
||||
{
|
||||
timeout.cancel();
|
||||
exit_called=true;
|
||||
BOOST_CHECK_EQUAL(exit, 42);
|
||||
})
|
||||
);
|
||||
|
||||
BOOST_REQUIRE(!ec);
|
||||
std::thread thr([&]{c.wait();});
|
||||
io_context.run();
|
||||
|
||||
BOOST_CHECK(exit_called);
|
||||
BOOST_CHECK_EQUAL(c.exit_code(), 42);
|
||||
thr.join();
|
||||
|
||||
}*/
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE( async );
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -101,3 +103,4 @@ BOOST_AUTO_TEST_CASE(emtpy_out, *boost::unit_test::timeout(2))
|
||||
BOOST_CHECK_EQUAL(fut.get(), "");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -23,6 +23,9 @@ 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;
|
||||
@@ -83,3 +86,57 @@ BOOST_AUTO_TEST_CASE(multithreaded_async_pipe)
|
||||
for (auto &t : threads)
|
||||
t.join();
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(move_pipe)
|
||||
{
|
||||
asio::io_context ios;
|
||||
|
||||
bp::async_pipe ap{ios};
|
||||
BOOST_TEST_CHECKPOINT("First move");
|
||||
bp::async_pipe ap2{std::move(ap)};
|
||||
BOOST_CHECK_EQUAL(ap.native_source(), ::boost::winapi::INVALID_HANDLE_VALUE_);
|
||||
BOOST_CHECK_EQUAL(ap.native_sink (), ::boost::winapi::INVALID_HANDLE_VALUE_);
|
||||
|
||||
BOOST_TEST_CHECKPOINT("Second move");
|
||||
ap = std::move(ap2);
|
||||
|
||||
{
|
||||
BOOST_TEST_CHECKPOINT("Third move, from closed");
|
||||
bp::async_pipe ap_inv{ios};
|
||||
ap_inv.close();
|
||||
ap = std::move(ap_inv);
|
||||
}
|
||||
|
||||
{
|
||||
BOOST_TEST_CHECKPOINT("Fourth move, from closed");
|
||||
bp::async_pipe ap_inv{ios};
|
||||
ap_inv.close();
|
||||
const auto ap3 = std::move(ap_inv);
|
||||
}
|
||||
|
||||
{
|
||||
//copy an a closed pipe
|
||||
BOOST_TEST_CHECKPOINT("Copy assign");
|
||||
BOOST_TEST_CHECKPOINT("Fourth move, from closed");
|
||||
bp::async_pipe ap_inv{ios};
|
||||
ap_inv.close();
|
||||
ap = ap_inv; //copy an invalid pipe
|
||||
}
|
||||
|
||||
{
|
||||
//copy an a closed pipe
|
||||
BOOST_TEST_CHECKPOINT("Copy assign");
|
||||
BOOST_TEST_CHECKPOINT("Fourth move, from closed");
|
||||
bp::async_pipe ap_inv{ios};
|
||||
ap_inv.close();
|
||||
BOOST_TEST_CHECKPOINT("Copy construct");
|
||||
bp::async_pipe ap4{ap_inv};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <array>
|
||||
|
||||
namespace bp = boost::process;
|
||||
BOOST_AUTO_TEST_SUITE( async );
|
||||
|
||||
BOOST_AUTO_TEST_CASE(future, *boost::unit_test::timeout(15))
|
||||
{
|
||||
@@ -59,3 +60,5 @@ 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,13 +15,16 @@
|
||||
|
||||
#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/strand.hpp>
|
||||
#include <boost/asio/use_future.hpp>
|
||||
#include <boost/asio/yield.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
BOOST_AUTO_TEST_SUITE( async );
|
||||
|
||||
namespace bp = boost::process;
|
||||
BOOST_AUTO_TEST_CASE(stackful, *boost::unit_test::timeout(15))
|
||||
@@ -44,9 +47,12 @@ BOOST_AUTO_TEST_CASE(stackful, *boost::unit_test::timeout(15))
|
||||
BOOST_CHECK(did_something_else);
|
||||
};
|
||||
|
||||
boost::asio::spawn(ios, stackful);
|
||||
ios.post([&]{did_something_else = true;});
|
||||
boost::asio::io_context::strand str{ios};
|
||||
boost::asio::post(str, [&]{boost::asio::spawn(ios, stackful);});
|
||||
boost::asio::post(str, [&]{did_something_else = true;});
|
||||
|
||||
ios.run();
|
||||
BOOST_CHECK(did_something_else);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#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>
|
||||
@@ -22,6 +23,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
BOOST_AUTO_TEST_SUITE( async );
|
||||
|
||||
namespace bp = boost::process;
|
||||
BOOST_AUTO_TEST_CASE(stackful, *boost::unit_test::timeout(15))
|
||||
@@ -45,7 +47,7 @@ BOOST_AUTO_TEST_CASE(stackful, *boost::unit_test::timeout(15))
|
||||
};
|
||||
|
||||
boost::asio::spawn(ios, stackful);
|
||||
ios.post([&]{did_something_else = true;});
|
||||
boost::asio::post(ios.get_executor(), [&]{did_something_else = true;});
|
||||
|
||||
ios.run();
|
||||
BOOST_CHECK(did_something_else);
|
||||
@@ -71,7 +73,7 @@ BOOST_AUTO_TEST_CASE(stackful_except, *boost::unit_test::timeout(15))
|
||||
};
|
||||
|
||||
boost::asio::spawn(ios, stackful);
|
||||
ios.post([&]{did_something_else = true;});
|
||||
boost::asio::post(ios.get_executor(), [&]{did_something_else = true;});
|
||||
ios.run();
|
||||
|
||||
BOOST_CHECK(did_something_else);
|
||||
@@ -100,8 +102,10 @@ BOOST_AUTO_TEST_CASE(stackful_error, *boost::unit_test::timeout(15))
|
||||
};
|
||||
|
||||
boost::asio::spawn(ios, stackful);
|
||||
ios.post([&]{did_something_else = true;});
|
||||
boost::asio::post(ios.get_executor(), [&]{did_something_else = true;});
|
||||
ios.run();
|
||||
|
||||
BOOST_CHECK(did_something_else);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#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>
|
||||
@@ -22,6 +23,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
BOOST_AUTO_TEST_SUITE( async );
|
||||
|
||||
namespace bp = boost::process;
|
||||
BOOST_AUTO_TEST_CASE(stackful_except, *boost::unit_test::timeout(15))
|
||||
@@ -44,10 +46,10 @@ BOOST_AUTO_TEST_CASE(stackful_except, *boost::unit_test::timeout(15))
|
||||
};
|
||||
|
||||
boost::asio::spawn(ios, stackful);
|
||||
ios.post([&]{did_something_else = true;});
|
||||
boost::asio::post(ios.get_executor(), [&]{did_something_else = true;});
|
||||
ios.run();
|
||||
|
||||
BOOST_CHECK(did_something_else);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#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>
|
||||
@@ -22,6 +23,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
BOOST_AUTO_TEST_SUITE( async );
|
||||
|
||||
namespace bp = boost::process;
|
||||
BOOST_AUTO_TEST_CASE(stackless, *boost::unit_test::timeout(15))
|
||||
@@ -57,10 +59,13 @@ BOOST_AUTO_TEST_CASE(stackless, *boost::unit_test::timeout(15))
|
||||
}
|
||||
} stackless{ios, did_something_else};
|
||||
|
||||
ios.post([&]{stackless();});
|
||||
ios.post([&]{did_something_else = true;});
|
||||
boost::asio::post(ios.get_executor(), [&]{stackless();});
|
||||
boost::asio::post(ios.get_executor(), [&]{did_something_else = true;});
|
||||
|
||||
ios.run();
|
||||
|
||||
BOOST_CHECK(did_something_else);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -39,6 +39,7 @@ 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))
|
||||
{
|
||||
@@ -150,3 +151,5 @@ BOOST_AUTO_TEST_CASE(file_io, *boost::unit_test::timeout(2))
|
||||
boost::filesystem::remove(pth);
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE( bind_stdin );
|
||||
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
# include <windows.h>
|
||||
@@ -255,3 +256,5 @@ BOOST_AUTO_TEST_CASE(file_io_C, *boost::unit_test::timeout(2))
|
||||
c.wait();
|
||||
boost::filesystem::remove(pth);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <iostream>
|
||||
|
||||
namespace bp = boost::process;
|
||||
BOOST_AUTO_TEST_SUITE( bind_stdin_stdout );
|
||||
|
||||
BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(10))
|
||||
{
|
||||
@@ -53,3 +54,5 @@ 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,6 +37,9 @@ 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;
|
||||
|
||||
@@ -164,3 +167,5 @@ BOOST_AUTO_TEST_CASE(file_io, *boost::unit_test::timeout(2))
|
||||
boost::filesystem::remove(pth);
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -35,6 +35,9 @@ 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;
|
||||
@@ -131,3 +134,5 @@ 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(closed)
|
||||
BOOST_AUTO_TEST_CASE(close_stderr)
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
namespace bp = boost::process;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(closed)
|
||||
BOOST_AUTO_TEST_CASE(close_stdin)
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
namespace bp = boost::process;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(closed)
|
||||
BOOST_AUTO_TEST_CASE(close_stdout)
|
||||
{
|
||||
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,11 +72,12 @@ BOOST_AUTO_TEST_CASE(sync_wait_abort)
|
||||
struct wait_handler
|
||||
{
|
||||
HANDLE handle_;
|
||||
|
||||
wait_handler(HANDLE handle) : handle_(handle) {}
|
||||
bool &called_;
|
||||
wait_handler(HANDLE handle, bool &called) : handle_(handle), called_(called) {}
|
||||
|
||||
void operator()(const boost::system::error_code &ec)
|
||||
{
|
||||
called_ = true;
|
||||
BOOST_REQUIRE(!ec);
|
||||
DWORD exit_code;
|
||||
BOOST_REQUIRE(GetExitCodeProcess(handle_, &exit_code));
|
||||
@@ -86,8 +87,13 @@ 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;
|
||||
@@ -104,9 +110,14 @@ 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());
|
||||
set.async_wait(wait_handler(wh_called));
|
||||
#endif
|
||||
|
||||
std::error_code ec;
|
||||
@@ -118,10 +129,31 @@ BOOST_AUTO_TEST_CASE(async_wait)
|
||||
BOOST_REQUIRE(!ec);
|
||||
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
windows::object_handle handle(io_context, c.native_handle());
|
||||
handle.async_wait(wait_handler(handle.native_handle()));
|
||||
windows::object_handle handle(io_context.get_executor(), c.native_handle());
|
||||
handle.async_wait(wait_handler(handle.native_handle(), wh_called));
|
||||
#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");
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_nowait)
|
||||
{
|
||||
// No need to call wait when passing an io_context
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
using namespace boost::asio;
|
||||
|
||||
std::error_code ec;
|
||||
boost::asio::io_context io_context;
|
||||
bp::child c(
|
||||
master_test_suite().argv[1],
|
||||
"test", "--exit-code", "221",
|
||||
ec,
|
||||
bp::on_exit=[](int exit_code, std::error_code) mutable {},
|
||||
io_context
|
||||
);
|
||||
BOOST_REQUIRE(!ec);
|
||||
io_context.run();
|
||||
BOOST_CHECK_EQUAL(221, c.exit_code());
|
||||
}
|
||||
@@ -33,6 +33,16 @@ 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;
|
||||
@@ -41,14 +51,14 @@ BOOST_AUTO_TEST_CASE(wait_group_test, *boost::unit_test::timeout(5))
|
||||
|
||||
bp::child c1(
|
||||
master_test_suite().argv[1],
|
||||
"--wait", "1",
|
||||
"--wait", "2",
|
||||
g,
|
||||
ec
|
||||
);
|
||||
|
||||
bp::child c2(
|
||||
master_test_suite().argv[1],
|
||||
"--wait", "1",
|
||||
"--wait", "2",
|
||||
g,
|
||||
ec
|
||||
);
|
||||
@@ -57,13 +67,17 @@ BOOST_AUTO_TEST_CASE(wait_group_test, *boost::unit_test::timeout(5))
|
||||
BOOST_CHECK(c2.running());
|
||||
|
||||
BOOST_REQUIRE(!ec);
|
||||
BOOST_REQUIRE(c1.in_group());
|
||||
BOOST_REQUIRE(c2.in_group());
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +85,15 @@ 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;
|
||||
|
||||
@@ -106,4 +129,7 @@ BOOST_AUTO_TEST_CASE(wait_group_test_timeout, *boost::unit_test::timeout(15))
|
||||
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,5 +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)
|
||||
|
||||
#include <boost/system/api_config.hpp>
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
#define BOOST_NO_ANSI_APIS 1
|
||||
#endif
|
||||
#include <boost/process.hpp>
|
||||
@@ -11,10 +11,14 @@
|
||||
#include <thread>
|
||||
|
||||
#include <boost/process/pipe.hpp>
|
||||
#include <boost/process/environment.hpp>
|
||||
|
||||
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;
|
||||
@@ -35,7 +39,8 @@ BOOST_AUTO_TEST_CASE(named, *boost::unit_test::timeout(2))
|
||||
#if defined( BOOST_WINDOWS_API )
|
||||
bp::pipe pipe("\\\\.\\pipe\\pipe_name");
|
||||
#elif defined( BOOST_POSIX_API )
|
||||
bp::pipe pipe("./test_pipe");
|
||||
const auto home_path = boost::this_process::environment()["HOME"].to_string();
|
||||
bp::pipe pipe(home_path + "/.boost_process_test_pipe");
|
||||
#endif
|
||||
|
||||
std::string in = "xyz";
|
||||
@@ -230,3 +235,4 @@ BOOST_AUTO_TEST_CASE(coverage, *boost::unit_test::timeout(5))
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE( pipe_tests );
|
||||
|
||||
namespace bp = boost::process;
|
||||
|
||||
@@ -50,6 +51,8 @@ BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(5))
|
||||
);
|
||||
BOOST_REQUIRE(!ec);
|
||||
|
||||
BOOST_TEST_INFO("Launching child 2");
|
||||
|
||||
bp::child c2(
|
||||
master_test_suite().argv[1],
|
||||
bp::args={"test", "--prefix-once", "hello "},
|
||||
@@ -74,3 +77,4 @@ BOOST_AUTO_TEST_CASE(sync_io, *boost::unit_test::timeout(5))
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <boost/process.hpp>
|
||||
#include <boost/process/posix.hpp>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <system_error>
|
||||
|
||||
|
||||
@@ -21,6 +23,7 @@
|
||||
#include <sys/wait.h>
|
||||
#include <errno.h>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
namespace bp = boost::process;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(bind_fd, *boost::unit_test::timeout(2))
|
||||
@@ -99,3 +102,67 @@ BOOST_AUTO_TEST_CASE(execve_throw_on_error, *boost::unit_test::timeout(2))
|
||||
BOOST_CHECK_EQUAL(e.code().value(), ENOENT);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(leak_test, *boost::unit_test::timeout(5))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
std::error_code ec;
|
||||
|
||||
const auto pid = boost::this_process::get_id();
|
||||
const auto fd_path = fs::path("/proc") / std::to_string(pid) / "fd";
|
||||
|
||||
auto get_fds = [&]{
|
||||
std::vector<int> fds;
|
||||
for (auto && fd : fs::directory_iterator(fd_path))
|
||||
fds.push_back(std::stoi(fd.path().filename().string()));
|
||||
return fds;
|
||||
};
|
||||
|
||||
std::vector<int> fd_list = get_fds();
|
||||
if (fd_list.empty()) //then there's no /proc in the current linux distribution.
|
||||
return;
|
||||
|
||||
|
||||
BOOST_CHECK(std::find(fd_list.begin(), fd_list.end(), STDOUT_FILENO) != fd_list.end());
|
||||
BOOST_CHECK(std::find(fd_list.begin(), fd_list.end(), STDIN_FILENO) != fd_list.end());
|
||||
BOOST_CHECK(std::find(fd_list.begin(), fd_list.end(), STDERR_FILENO) != fd_list.end());
|
||||
|
||||
bp::pipe p; //should add two descriptors.
|
||||
|
||||
auto fd_list_new = get_fds();
|
||||
|
||||
BOOST_CHECK_EQUAL(fd_list_new.size(), fd_list.size() + 2);
|
||||
fd_list.push_back(p.native_source());
|
||||
fd_list.push_back(p.native_sink());
|
||||
|
||||
|
||||
BOOST_CHECK_EQUAL(
|
||||
bp::system(
|
||||
master_test_suite().argv[1],
|
||||
"test", "--exit-code", "123", ec), 123);
|
||||
|
||||
fd_list_new = get_fds();
|
||||
BOOST_CHECK_EQUAL(fd_list.size(), fd_list_new.size());
|
||||
|
||||
|
||||
const int native_source = p.native_source();
|
||||
BOOST_CHECK_EQUAL(
|
||||
bp::system(
|
||||
master_test_suite().argv[1],
|
||||
bp::std_in < p,
|
||||
"test", "--exit-code", "123", ec), 123);
|
||||
|
||||
BOOST_CHECK(!ec);
|
||||
|
||||
////now, p.source should be closed, so we remove it from fd_list
|
||||
|
||||
const auto itr = std::find(fd_list.begin(), fd_list.end(), native_source);
|
||||
if (itr != fd_list.end())
|
||||
fd_list.erase(itr);
|
||||
|
||||
fd_list_new = get_fds();
|
||||
|
||||
BOOST_CHECK_EQUAL(fd_list.size(), fd_list_new.size());
|
||||
|
||||
}
|
||||
@@ -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_io, *boost::unit_test::timeout(5))
|
||||
BOOST_AUTO_TEST_CASE(sync_spawn, *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_io, *boost::unit_test::timeout(2))
|
||||
BOOST_AUTO_TEST_CASE(async_spawn, *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(exit_code, *boost::unit_test::timeout(5))
|
||||
BOOST_AUTO_TEST_CASE(system_exit_code, *boost::unit_test::timeout(5))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
|
||||
@@ -70,17 +70,19 @@ BOOST_AUTO_TEST_CASE(explicit_async_io_running, *boost::unit_test::timeout(10))
|
||||
std::future<std::string> fut;
|
||||
std::error_code ec;
|
||||
|
||||
ios.post([&]
|
||||
{
|
||||
bp::system(
|
||||
master_test_suite().argv[1],
|
||||
"test", "--echo-stdout", "abc",
|
||||
bp::std_out > fut,
|
||||
ios,
|
||||
ec
|
||||
);
|
||||
BOOST_REQUIRE(!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.run();
|
||||
|
||||
@@ -22,8 +22,17 @@
|
||||
|
||||
namespace bp = boost::process;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(terminate_set_on_error)
|
||||
BOOST_AUTO_TEST_CASE(terminate_set_on_error, *boost::unit_test::timeout(5))
|
||||
{
|
||||
std::atomic<bool> done{false};
|
||||
std::thread thr{
|
||||
[&]
|
||||
{
|
||||
for (int i = 0; i < 50 && !done.load(); i++)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
BOOST_REQUIRE(done.load());
|
||||
}};
|
||||
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
std::error_code ec;
|
||||
bp::child c(
|
||||
@@ -44,10 +53,22 @@ BOOST_AUTO_TEST_CASE(terminate_set_on_error)
|
||||
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_AUTO_TEST_CASE(terminate_throw_on_error, *boost::unit_test::timeout(5))
|
||||
{
|
||||
std::atomic<bool> done{false};
|
||||
std::thread thr{
|
||||
[&]
|
||||
{
|
||||
for (int i = 0; i < 50 && !done.load(); i++)
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
BOOST_REQUIRE(done.load());
|
||||
}};
|
||||
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
std::error_code ec;
|
||||
@@ -68,4 +89,7 @@ BOOST_AUTO_TEST_CASE(terminate_throw_on_error)
|
||||
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,6 +24,9 @@
|
||||
|
||||
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;
|
||||
@@ -40,7 +43,7 @@ BOOST_AUTO_TEST_CASE(sync_wait, *boost::unit_test::timeout(2))
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(2))
|
||||
BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(4))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
using namespace boost::asio;
|
||||
@@ -50,6 +53,10 @@ BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(2))
|
||||
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"},
|
||||
@@ -64,3 +71,5 @@ BOOST_AUTO_TEST_CASE(async_wait, *boost::unit_test::timeout(2))
|
||||
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,12 +22,15 @@
|
||||
#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"},
|
||||
@@ -35,8 +38,13 @@ 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)
|
||||
@@ -101,4 +109,6 @@ 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(args, *boost::unit_test::timeout(2))
|
||||
BOOST_AUTO_TEST_CASE(wargs, *boost::unit_test::timeout(2))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
@@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE(args, *boost::unit_test::timeout(2))
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(cmd, *boost::unit_test::timeout(2))
|
||||
BOOST_AUTO_TEST_CASE(wcmd, *boost::unit_test::timeout(2))
|
||||
{
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user