mirror of
https://github.com/boostorg/process.git
synced 2026-01-20 04:42:24 +00:00
Compare commits
12 Commits
sfinae_dyn
...
new_wait_f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0edff5449a | ||
|
|
417ea77f2f | ||
|
|
66c2867371 | ||
|
|
caa7b2fcc8 | ||
|
|
2314e19f12 | ||
|
|
2aa5e1461c | ||
|
|
61fa15fa48 | ||
|
|
92508e06a1 | ||
|
|
8d48d9cbfa | ||
|
|
f25c31c847 | ||
|
|
3eacae5e38 | ||
|
|
881da4f9e2 |
@@ -70,6 +70,7 @@ jobs:
|
||||
|
||||
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
|
||||
cd ../../..
|
||||
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"
|
||||
|
||||
@@ -105,6 +105,8 @@ script:
|
||||
# `--coverage` flags required to generate coverage info for Coveralls
|
||||
- ../../../b2 $MULTITHREAD with-valgrind address-model=64 architecture=x86 $USE_VALGRIND toolset=$TOOLSET cxxflags="--coverage -DBOOST_TRAVISCI_BUILD -std=$CXX_STANDARD" linkflags="--coverage" -sBOOST_BUILD_PATH=.
|
||||
- ../../../b2 $MULTITHREAD without-valgrind address-model=64 architecture=x86 toolset=$TOOLSET cxxflags="--coverage -DBOOST_TRAVISCI_BUILD -std=$CXX_STANDARD" linkflags="--coverage" -sBOOST_BUILD_PATH=.
|
||||
- cat /home/travis/boost-local/libs/boost-process/test/report_wait_for.xml
|
||||
- cat /home/travis/boost-local/libs/boost-process/test/log_wait_for.xml
|
||||
after_success:
|
||||
# Copying Coveralls data to a separate folder
|
||||
- mkdir -p $TRAVIS_BUILD_DIR/coverals
|
||||
@@ -133,6 +135,6 @@ after_success:
|
||||
- coveralls-lcov coverals/coverage.info
|
||||
|
||||
after_script:
|
||||
- curl -s https://report.ci/upload.py | python - --token=$REPORT_CI_TOKEN --name="$BADGE test run"
|
||||
- curl -s https://report.ci/upload.py | python - --name="$BADGE test run"
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ In that it is different than other facilities (like sockets) and provides anothe
|
||||
Pipes are typically used for interprocess communication. The main reason is, that pipes can be directly assigned to the process stdio, i.e. stderr, stdin and stdout.
|
||||
Additionally, half of the pipe can be inherited to the child process and closed in the father process. This will cause the pipe to be broken when the child process exits.
|
||||
|
||||
Though please not, that if the the same thread reads and write to a pipe, it will only talk to itself.
|
||||
Though please note, that if the the same thread reads and write to a pipe, it will only talk to itself.
|
||||
|
||||
[section:anonymous Anonymous Pipes]
|
||||
|
||||
|
||||
@@ -10,13 +10,11 @@
|
||||
|
||||
namespace boost { namespace asio {
|
||||
|
||||
template<typename T>
|
||||
struct is_mutable_buffer_sequence;
|
||||
|
||||
template<typename T>
|
||||
struct is_const_buffer_sequence;
|
||||
|
||||
class mutable_buffer;
|
||||
class mutable_buffers_1;
|
||||
|
||||
class const_buffer;
|
||||
class const_buffers_1;
|
||||
|
||||
template<typename Allocator>
|
||||
class basic_streambuf;
|
||||
|
||||
@@ -52,8 +52,10 @@ template<typename Executor>
|
||||
void pipe_out<1,-1>::on_exec_setup(Executor &e) const
|
||||
{
|
||||
if (::dup2(sink, STDOUT_FILENO) == -1)
|
||||
e.set_error(::boost::process::detail::get_last_error(), "dup3() failed");
|
||||
::close(sink);
|
||||
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
|
||||
|
||||
if (sink != STDOUT_FILENO)
|
||||
::close(sink);
|
||||
::close(source);
|
||||
}
|
||||
|
||||
@@ -63,7 +65,9 @@ void pipe_out<2,-1>::on_exec_setup(Executor &e) const
|
||||
{
|
||||
if (::dup2(sink, STDERR_FILENO) == -1)
|
||||
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
|
||||
::close(sink);
|
||||
|
||||
if (sink != STDOUT_FILENO)
|
||||
::close(sink);
|
||||
::close(source);
|
||||
}
|
||||
|
||||
@@ -75,8 +79,8 @@ void pipe_out<1,2>::on_exec_setup(Executor &e) const
|
||||
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
|
||||
if (::dup2(sink, STDERR_FILENO) == -1)
|
||||
e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
|
||||
::close(sink);
|
||||
::close(source);
|
||||
if ((sink != STDOUT_FILENO) && (sink != STDERR_FILENO))
|
||||
::close(sink);
|
||||
}
|
||||
|
||||
class async_pipe;
|
||||
|
||||
@@ -111,11 +111,14 @@ inline bool wait_until(
|
||||
}
|
||||
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);
|
||||
do
|
||||
{
|
||||
auto ts = get_timespec(time_out - Clock::now());
|
||||
::timespec rem;
|
||||
::nanosleep(&ts, &rem);
|
||||
}
|
||||
while (rem.tv_sec > 0 || rem.tv_nsec > 0);
|
||||
|
||||
::exit(0);
|
||||
}
|
||||
|
||||
@@ -125,8 +128,8 @@ inline bool wait_until(
|
||||
~child_cleaner_t()
|
||||
{
|
||||
int res;
|
||||
::kill(pid, -15);
|
||||
::waitpid(pid, &res, WNOHANG);
|
||||
::kill(pid, SIGTERM);
|
||||
::waitpid(pid, &res, 0);
|
||||
}
|
||||
};
|
||||
child_cleaner_t child_cleaner{timeout_pid};
|
||||
|
||||
@@ -117,9 +117,13 @@ inline bool wait_until(
|
||||
}
|
||||
else if (timeout_pid == 0)
|
||||
{
|
||||
auto ts = get_timespec(time_out - Clock::now());
|
||||
::setpgid(0, p.grp);
|
||||
::nanosleep(&ts, nullptr);
|
||||
do
|
||||
{
|
||||
auto ts = get_timespec(time_out - Clock::now());
|
||||
::timespec rem;
|
||||
::nanosleep(&ts, &rem);
|
||||
}
|
||||
while (rem.tv_sec > 0 || rem.tv_nsec > 0);
|
||||
::exit(0);
|
||||
}
|
||||
|
||||
@@ -129,7 +133,7 @@ inline bool wait_until(
|
||||
~child_cleaner_t()
|
||||
{
|
||||
int res;
|
||||
::kill(pid, -15);
|
||||
::kill(pid, SIGKILL);
|
||||
::waitpid(pid, &res, WNOHANG);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10,12 +10,10 @@
|
||||
|
||||
namespace boost { namespace asio {
|
||||
|
||||
template<typename T>
|
||||
struct is_mutable_buffer_sequence;
|
||||
|
||||
template<typename T>
|
||||
struct is_const_buffer_sequence;
|
||||
|
||||
class mutable_buffer;
|
||||
class mutable_buffers_1;
|
||||
class const_buffer;
|
||||
class const_buffers_1;
|
||||
|
||||
template<typename Allocator>
|
||||
class basic_streambuf;
|
||||
|
||||
@@ -122,6 +122,20 @@ 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;
|
||||
|
||||
@@ -163,25 +177,19 @@ 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>
|
||||
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;}
|
||||
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;}
|
||||
|
||||
};
|
||||
|
||||
@@ -226,24 +234,13 @@ 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;}
|
||||
|
||||
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_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 ;}
|
||||
|
||||
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;}
|
||||
|
||||
@@ -111,4 +111,26 @@ BOOST_AUTO_TEST_CASE(wait_until_ec)
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(wait_for_exit_before_timeout)
|
||||
{
|
||||
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"},
|
||||
ec
|
||||
);
|
||||
BOOST_REQUIRE(!ec);
|
||||
|
||||
BOOST_CHECK(c.wait_for(std::chrono::seconds(20)));
|
||||
|
||||
auto timeout_t = std::chrono::system_clock::now();
|
||||
|
||||
// check that we didn't wait the entire timeout period
|
||||
BOOST_CHECK_LT(std::chrono::duration_cast<std::chrono::seconds>(timeout_t - launch_time).count(), 20);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
||||
Reference in New Issue
Block a user