diff --git a/doc/acknowledgements.qbk b/doc/acknowledgements.qbk index 4442512c..06986812 100644 --- a/doc/acknowledgements.qbk +++ b/doc/acknowledgements.qbk @@ -8,4 +8,6 @@ A special thank you goes to [@http://www.intra2net.com/ Intra2net AG] (especiall Great thanks also goes to Boris Schaeling, who despite having boost.process rejected, went on to work on it and maintained it up until this day and participated in the development of the current version. +Many Thanks, to [@https://github.com/time-killer-games Samuel Venable] for contributing the v2::ext functionality and all the research that went into it. + [endsect] diff --git a/include/boost/process/environment.hpp b/include/boost/process/environment.hpp index dc9e99df..3aa4c916 100644 --- a/include/boost/process/environment.hpp +++ b/include/boost/process/environment.hpp @@ -263,7 +263,7 @@ public: auto st1 = key + ::boost::process::detail::equal_sign(); while (*p != nullptr) { - const auto len = std::char_traits::length(*p); + const int len = std::char_traits::length(*p); if ((std::distance(st1.begin(), st1.end()) < len) && std::equal(st1.begin(), st1.end(), *p)) break; diff --git a/include/boost/process/v2/detail/process_handle_signal.hpp b/include/boost/process/v2/detail/process_handle_signal.hpp index 00f7bbcc..1ebd5a59 100644 --- a/include/boost/process/v2/detail/process_handle_signal.hpp +++ b/include/boost/process/v2/detail/process_handle_signal.hpp @@ -101,9 +101,8 @@ struct basic_process_handle_signal handle.pid_ = -1; } - pid_type id() const - { return pid_; } - native_handle_type native_handle() {return pid_;} + pid_type id() const { return pid_; } + native_handle_type native_handle() {return {};} void terminate_if_running(error_code &) { diff --git a/include/boost/process/v2/ext.hpp b/include/boost/process/v2/ext.hpp new file mode 100644 index 00000000..e47b5a91 --- /dev/null +++ b/include/boost/process/v2/ext.hpp @@ -0,0 +1,16 @@ +// +// Copyright (c) 2023 Klemens Morgenstern (klemens.morgenstern@gmx.net) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_PROCESS_V2_EXT_HPP +#define BOOST_PROCESS_V2_EXT_HPP + +#include +#include +#include +#include + +#endif //BOOST_PROCESS_V2_EXT_HPP diff --git a/include/boost/process/v2/ext/cmd.hpp b/include/boost/process/v2/ext/cmd.hpp index beca4ffd..a92c9c0a 100644 --- a/include/boost/process/v2/ext/cmd.hpp +++ b/include/boost/process/v2/ext/cmd.hpp @@ -20,7 +20,8 @@ BOOST_PROCESS_V2_BEGIN_NAMESPACE namespace ext { -/// Get the argument vector from a given pid +/// @{ +/// Get the argument vector of another process BOOST_PROCESS_V2_DECL shell cmd(pid_type pid, error_code & ec); BOOST_PROCESS_V2_DECL shell cmd(pid_type pid); @@ -32,15 +33,25 @@ BOOST_PROCESS_V2_DECL shell cmd(HANDLE handle); template BOOST_PROCESS_V2_DECL shell cmd(basic_process_handle & handle, error_code & ec) { +#if defined(BOOST_PROCESS_V2_WINDOWS) return cmd(handle.native_handle(), ec); +#else + return cmd(handle.id(), ec); +#endif } template BOOST_PROCESS_V2_DECL shell cmd(basic_process_handle & handle) { +#if defined(BOOST_PROCESS_V2_WINDOWS) return cmd(handle.native_handle()); +#else + return cmd(handle.id()); +#endif } +/// @} + } // namespace ext BOOST_PROCESS_V2_END_NAMESPACE diff --git a/include/boost/process/v2/ext/cwd.hpp b/include/boost/process/v2/ext/cwd.hpp index ec069316..3af8358e 100644 --- a/include/boost/process/v2/ext/cwd.hpp +++ b/include/boost/process/v2/ext/cwd.hpp @@ -15,26 +15,38 @@ BOOST_PROCESS_V2_BEGIN_NAMESPACE namespace ext { -/// Obtain the current path of a process +/// @{ +/// Obtain the current path of another process BOOST_PROCESS_V2_DECL filesystem::path cwd(pid_type pid, error_code & ec); BOOST_PROCESS_V2_DECL filesystem::path cwd(pid_type pid); +template +BOOST_PROCESS_V2_DECL filesystem::path cwd(basic_process_handle & handle, error_code & ec) +{ +#if defined(BOOST_PROCESS_V2_WINDOWS) + return cwd(handle.native_handle(), ec); +#else + return cwd(handle.id(), ec); +#endif +} + +template +BOOST_PROCESS_V2_DECL filesystem::path cwd(basic_process_handle & handle) +{ +#if defined(BOOST_PROCESS_V2_WINDOWS) + return cwd(handle.native_handle()); +#else + return cwd(handle.id()); +#endif +} + +/// @} + #if defined(BOOST_PROCESS_V2_WINDOWS) BOOST_PROCESS_V2_DECL filesystem::path cwd(HANDLE handle, error_code & ec); BOOST_PROCESS_V2_DECL filesystem::path cwd(HANDLE handle); #endif -template -BOOST_PROCESS_V2_DECL filesystem::path cwd(basic_process_handle & handle, error_code & ec) -{ - return cwd(handle.native_handle(), ec); -} - -template -BOOST_PROCESS_V2_DECL filesystem::path cwd(basic_process_handle & handle) -{ - return cwd(handle.native_handle()); -} } // namespace ext diff --git a/include/boost/process/v2/ext/env.hpp b/include/boost/process/v2/ext/env.hpp index daf2eac8..7adc8400 100644 --- a/include/boost/process/v2/ext/env.hpp +++ b/include/boost/process/v2/ext/env.hpp @@ -26,6 +26,9 @@ namespace ext #if defined(BOOST_PROCESS_V2_WINDOWS) using native_env_handle_type = wchar_t *; using native_env_iterator = wchar_t *; +#elif defined(__FreeBSD__) +using native_env_handle_type = char **; +using native_env_iterator = char **; #else using native_env_handle_type = char *; using native_env_iterator = char *; @@ -45,6 +48,7 @@ BOOST_PROCESS_V2_DECL const environment::char_type * dereference(native_env_iter namespace ext { +/// The view of an environment struct env_view { using native_handle_type = detail::ext::native_env_handle_type; @@ -105,26 +109,38 @@ struct env_view detail::ext::native_env_handle_deleter> handle_; }; -/// Get the argument vector from a given pid +/// @{ +/// Get the environment of another process. BOOST_PROCESS_V2_DECL env_view env(pid_type pid, error_code & ec); BOOST_PROCESS_V2_DECL env_view env(pid_type pid); +template +BOOST_PROCESS_V2_DECL env_view env(basic_process_handle & handle, error_code & ec) +{ +#if defined(BOOST_PROCESS_V2_WINDOWS) + return env(handle.native_handle(), ec); +#else + return env(handle.id(), ec); +#endif +} + +template +BOOST_PROCESS_V2_DECL env_view env(basic_process_handle & handle) +{ +#if defined(BOOST_PROCESS_V2_WINDOWS) + return env(handle.native_handle()); +#else + return env(handle.id()); +#endif +} + +/// @} + #if defined(BOOST_PROCESS_V2_WINDOWS) BOOST_PROCESS_V2_DECL env_view env(HANDLE handle, error_code & ec); BOOST_PROCESS_V2_DECL env_view env(HANDLE handle); #endif -template -BOOST_PROCESS_V2_DECL env_view env(basic_process_handle & handle, error_code & ec) -{ - return env(handle.native_handle(), ec); -} - -template -BOOST_PROCESS_V2_DECL env_view env(basic_process_handle & handle) -{ - return env(handle.native_handle()); -} } // namespace ext diff --git a/include/boost/process/v2/ext/exe.hpp b/include/boost/process/v2/ext/exe.hpp index 8b48ddfd..0629eb96 100644 --- a/include/boost/process/v2/ext/exe.hpp +++ b/include/boost/process/v2/ext/exe.hpp @@ -16,27 +16,40 @@ BOOST_PROCESS_V2_BEGIN_NAMESPACE namespace ext { -/// Return the executable path from pid +/// @{ +/// Return the executable of another process by pid or handle. BOOST_PROCESS_V2_DECL filesystem::path exe(pid_type pid, error_code & ec); BOOST_PROCESS_V2_DECL filesystem::path exe(pid_type pid); -#if defined(BOOST_PROCESS_V2_WINDOWS) -BOOST_PROCESS_V2_DECL filesystem::path exe(HANDLE handle, error_code & ec); -BOOST_PROCESS_V2_DECL filesystem::path exe(HANDLE handle); -#endif + template filesystem::path exe(basic_process_handle & handle, error_code & ec) { +#if defined(BOOST_PROCESS_V2_WINDOWS) return exe(handle.native_handle(), ec); +#else + return exe(handle.id(), ec); +#endif } template filesystem::path exe(basic_process_handle & handle) { +#if defined(BOOST_PROCESS_V2_WINDOWS) return exe(handle.native_handle()); +#else + return exe(handle.id()); +#endif } +///@} + +#if defined(BOOST_PROCESS_V2_WINDOWS) +BOOST_PROCESS_V2_DECL filesystem::path exe(HANDLE handle, error_code & ec); +BOOST_PROCESS_V2_DECL filesystem::path exe(HANDLE handle); +#endif + } // namespace ext BOOST_PROCESS_V2_END_NAMESPACE diff --git a/include/boost/process/v2/ext/impl/cmd.ipp b/include/boost/process/v2/ext/impl/cmd.ipp index 466a4151..efe20193 100644 --- a/include/boost/process/v2/ext/impl/cmd.ipp +++ b/include/boost/process/v2/ext/impl/cmd.ipp @@ -92,13 +92,12 @@ struct make_cmd_shell_ str_lengths += (std::strlen(*c) + 1); } // yes, not the greatest solution. - std::string buffer; res.buffer_.resize(str_lengths); res.argv_ = new char*[res.argc_ + 1]; res.free_argv_ = +[](int argc, char ** argv) {delete[] argv;}; res.argv_[res.argc_] = nullptr; - auto p = &buffer[sizeof(int) * (res.argc_) + 1]; + auto p = &*res.buffer_.begin(); for (int i = 0; i < res.argc_; i++) { @@ -179,7 +178,7 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) return {}; } - int argc = *reinterpret_cast(procargs.data()); + int argc = *reinterpret_cast(procargs.data()); auto itr = procargs.begin() + sizeof(argc); std::unique_ptr argv{new char*[argc + 1]}; @@ -305,16 +304,9 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) ec = detail::get_last_error(); return {}; } - struct free_argv - { - struct procstat * proc_stat; - ~free_argv() - { - procstat_freeargv(proc_stat); - } - }; - - return make_cmd_shell_::clone(cmd); + auto res = make_cmd_shell_::clone(cmd); + procstat_freeargv(proc_stat.get()); + return res; } #elif defined(__DragonFly__) diff --git a/include/boost/process/v2/ext/impl/cwd.ipp b/include/boost/process/v2/ext/impl/cwd.ipp index a4a4e45b..0afb14c1 100644 --- a/include/boost/process/v2/ext/impl/cwd.ipp +++ b/include/boost/process/v2/ext/impl/cwd.ipp @@ -101,10 +101,10 @@ filesystem::path cwd(HANDLE proc) filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec) { proc_vnodepathinfo vpi; - if (proc_pidinfo(pid, PROC_PIDVNODEPATHINFO, 0, &vpi, sizeof(vpi)) > 0) { + if (proc_pidinfo(pid, PROC_PIDVNODEPATHINFO, 0, &vpi, sizeof(vpi)) > 0) return filesystem::canonical(vpi.pvi_cdir.vip_path, ec); - } - ec = detail::get_last_error(); + else + ec = detail::get_last_error(); return ""; } diff --git a/include/boost/process/v2/ext/impl/env.ipp b/include/boost/process/v2/ext/impl/env.ipp index 7143d907..e4eee7dc 100644 --- a/include/boost/process/v2/ext/impl/env.ipp +++ b/include/boost/process/v2/ext/impl/env.ipp @@ -77,7 +77,7 @@ const environment::char_type * dereference(native_env_iterator iterator) return iterator; } -#else +#elif (defined(__APPLE___) || defined(__MACH__)) void native_env_handle_deleter::operator()(native_env_handle_type h) const { @@ -97,6 +97,36 @@ native_env_iterator find_end(native_env_iterator nh) return nh ; } +const environment::char_type * dereference(native_env_iterator iterator) +{ + return iterator; +} + + +#elif defined(__FreeBSD__) + +void native_env_handle_deleter::operator()(native_env_handle_type h) const +{ + delete [] h; +} + +native_env_iterator next(native_env_iterator nh) +{ + return ++nh ; +} +native_env_iterator find_end(native_env_iterator nh) +{ + while (*nh != nullptr) + nh++; + + return nh ; +} + +const environment::char_type * dereference(native_env_iterator iterator) +{ + return *iterator; +} + #endif } @@ -206,34 +236,35 @@ env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec) ec = detail::get_last_error(); return {}; } - + std::uint32_t nargs; memcpy(&nargs, &*procargs.begin(), sizeof(nargs)); char *cp = &*procargs.begin() + sizeof(nargs); - for (; cp < &&*procargs.begin()[size]; cp++) { - if (*cp == '\0') break; - } + for (; cp < &*procargs.end(); cp++) + if (*cp == '\0') + break; - if (cp == &procargs[s]) { + + if (cp == &procargs[size]) return {}; - } - for (; cp < &&*procargs.begin()[size]; cp++) { + + for (; cp < &*procargs.end(); cp++) if (*cp != '\0') break; - } - if (cp == &&*procargs.begin()[size]) { + + if (cp == &*procargs.end()) return {}; - } + int i = 0; char *sp = cp; std::vector vec; - while ((*sp != '\0' || i < nargs) && sp < &&*procargs.begin()[size]) { - if (i >= nargs) { + while ((*sp != '\0' || i < nargs) && sp < &*procargs.end()) { + if (i >= nargs) vec.push_back(*sp); - } + sp += 1; } @@ -279,6 +310,69 @@ env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec) return ev; } +#elif defined(__FreeBSD__) +env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + env_view ev; + + unsigned cntp = 0; + procstat *proc_stat = procstat_open_sysctl(); + if (proc_stat != nullptr) + { + kinfo_proc *proc_info = procstat_getprocs(proc_stat, KERN_PROC_PID, pid, &cntp); + if (proc_info != nullptr) + { + char **env = procstat_getenvv(proc_stat, proc_info, 0); + if (env != nullptr) + { + auto e = env; + std::size_t n = 0u, len = 0u; + while (e && *e != nullptr) + { + n ++; + len += std::strlen(*e); + e++; + } + std::size_t mem_needed = + // environ - nullptr - strlen + null terminators + (n * sizeof(char*)) + sizeof(char*) + len + n; + + char * out = new (std::nothrow) char[mem_needed]; + if (out != nullptr) + { + auto eno = reinterpret_cast(out); + auto eeo = eno; + auto str = out + (n * sizeof(char*)) + sizeof(char*); + e = env; + while (*e != nullptr) + { + auto len = std::strlen(*e) + 1u; + std::memcpy(str, *e, len); + *eno = str; + str += len; + eno ++; + e++; + } + *eno = nullptr; + + ev.handle_.reset(eeo); + } + else + ec = detail::get_last_error(); + + } + procstat_freeprocs(proc_stat, proc_info); + + } + else + ec = detail::get_last_error(); + procstat_close(proc_stat); + } + else + ec = detail::get_last_error(); + return ev; +} + #endif env_view env(boost::process::v2::pid_type pid) diff --git a/include/boost/process/v2/ext/impl/exe.ipp b/include/boost/process/v2/ext/impl/exe.ipp index fa772821..18f981bc 100644 --- a/include/boost/process/v2/ext/impl/exe.ipp +++ b/include/boost/process/v2/ext/impl/exe.ipp @@ -154,7 +154,8 @@ filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code strbuff.resize(len); if (sysctl(mib, 4, &strbuff[0], &len, nullptr, 0) == 0) { - return filesystem::canonical(strbuff, ec); + strbuff.resize(len - 1); + return filesystem::canonical(strbuff, ec); } } diff --git a/include/boost/process/v2/impl/pid.ipp b/include/boost/process/v2/impl/pid.ipp index 37dae095..aa3d164b 100644 --- a/include/boost/process/v2/impl/pid.ipp +++ b/include/boost/process/v2/impl/pid.ipp @@ -177,7 +177,7 @@ std::vector child_pids(pid_type pid, boost::system::error_code & ec) { std::vector vec; vec.reserve(proc_listpids(PROC_PPID_ONLY, (uint32_t)pid, nullptr, 0)); - if (proc_listpids(PROC_PPID_ONLY, (uint32_t)pid, &proc_info[0], sizeof(pid_type) * cntp)) + if (proc_listpids(PROC_PPID_ONLY, (uint32_t)pid, &vec[0], sizeof(pid_type) * vec.size())) { ec = detail::get_last_error(); return {}; diff --git a/include/boost/process/v2/impl/shell.ipp b/include/boost/process/v2/impl/shell.ipp index 7a54f038..12a9fa2c 100644 --- a/include/boost/process/v2/impl/shell.ipp +++ b/include/boost/process/v2/impl/shell.ipp @@ -111,7 +111,7 @@ void shell::parse_() shell::~shell() { - if (argv_ != nullptr && free_argv_) + if (argv_ != nullptr && free_argv_ != nullptr) free_argv_(argc_, argv_); } diff --git a/include/boost/process/v2/process.hpp b/include/boost/process/v2/process.hpp index 6c987a8b..ad5f9859 100644 --- a/include/boost/process/v2/process.hpp +++ b/include/boost/process/v2/process.hpp @@ -215,13 +215,13 @@ struct basic_process process_handle_.request_exit(ec); } - /// Send the process a signal requesting it to stop. This may rely on undocmented functions. + /// Send the process a signal requesting it to stop. This may rely on undocumented functions. void suspend(error_code &ec) { process_handle_.suspend(ec); } - /// Send the process a signal requesting it to stop. This may rely on undocmented functions. + /// Send the process a signal requesting it to stop. This may rely on undocumented functions. void suspend() { error_code ec; @@ -231,13 +231,13 @@ struct basic_process } - /// Send the process a signal requesting it to resume. This may rely on undocmented functions. + /// Send the process a signal requesting it to resume. This may rely on undocumented functions. void resume(error_code &ec) { process_handle_.resume(ec); } - /// Send the process a signal requesting it to resume. This may rely on undocmented functions. + /// Send the process a signal requesting it to resume. This may rely on undocumented functions. void resume() { error_code ec; diff --git a/test/v2/Jamfile.jam b/test/v2/Jamfile.jam index f15cc1db..30262035 100644 --- a/test/v2/Jamfile.jam +++ b/test/v2/Jamfile.jam @@ -59,13 +59,13 @@ test-suite standalone : [ run utf8.cpp test_impl ] [ run cstring_ref.cpp test_impl ] [ run environment.cpp test_impl ] - [ run pid.cpp test_impl ] + [ run pid.cpp test_impl : : : darwin:no ] [ run shell.cpp test_impl ] ; test-suite with_target : [ run process.cpp test_impl : --log_level=all --catch_system_errors=no -- : target ] [ run windows.cpp test_impl : --log_level=all --catch_system_errors=no -- : target : no windows:yes windows:Advapi32 ] - [ run ext.cpp test_impl : --log_level=all --catch_system_errors=no -- : target ] + [ run ext.cpp test_impl : --log_level=all --catch_system_errors=no -- : target : darwin:no ] ; diff --git a/test/v2/ext.cpp b/test/v2/ext.cpp index cab6ec13..c82a09ff 100644 --- a/test/v2/ext.cpp +++ b/test/v2/ext.cpp @@ -22,7 +22,8 @@ BOOST_AUTO_TEST_CASE(test_exe) namespace bp2 = boost::process::v2; auto pth = bp2::ext::exe(bp2::current_pid()); BOOST_CHECK(!pth.empty()); - BOOST_CHECK_EQUAL(master_test_suite().argv[0], pth.string()); + BOOST_CHECK_EQUAL(bp2::filesystem::canonical(master_test_suite().argv[0]).string(), + bp2::filesystem::canonical(pth).string()); } @@ -30,7 +31,7 @@ BOOST_AUTO_TEST_CASE(test_child_exe) { namespace bp2 = boost::process::v2; using boost::unit_test::framework::master_test_suite; - const auto pth = bp2::filesystem::canonical(master_test_suite().argv[1]); + const auto pth = bp2::filesystem::canonical(master_test_suite().argv[0]); boost::asio::io_context ctx; bp2::process proc(ctx, pth, {"sleep", "10000"}); @@ -66,7 +67,7 @@ BOOST_AUTO_TEST_CASE(cmd) BOOST_AUTO_TEST_CASE(cmd_exe) { using boost::unit_test::framework::master_test_suite; - const auto pth = master_test_suite().argv[1]; + const auto pth = master_test_suite().argv[0]; namespace bp2 = boost::process::v2; @@ -101,8 +102,8 @@ BOOST_AUTO_TEST_CASE(test_cwd) BOOST_AUTO_TEST_CASE(test_cwd_exe) { using boost::unit_test::framework::master_test_suite; - const auto pth = master_test_suite().argv[1]; namespace bp2 = boost::process::v2; + const auto pth = bp2::filesystem::absolute(master_test_suite().argv[0]); auto tmp = bp2::filesystem::temp_directory_path(); @@ -122,6 +123,7 @@ BOOST_AUTO_TEST_CASE(test_env) namespace bp2 = boost::process::v2; auto env = bp2::ext::env(bp2::current_pid()); + std::size_t e = 0; for (const auto & kp : bp2::environment::current()) { @@ -130,15 +132,20 @@ BOOST_AUTO_TEST_CASE(test_env) { return kp.key() == kp_.key(); }); - BOOST_REQUIRE(itr != env.end()); - BOOST_CHECK_EQUAL(kp.value(), (*itr).value()); + if (itr != env.end()) + { + BOOST_CHECK_EQUAL(kp.value(), (*itr).value()); + e++; + } + } + BOOST_CHECK_GT(e, 0u); } BOOST_AUTO_TEST_CASE(test_env_exe) { using boost::unit_test::framework::master_test_suite; - const auto pth = master_test_suite().argv[1]; + const auto pth = master_test_suite().argv[0]; namespace bp2 = boost::process::v2; auto tmp = bp2::filesystem::temp_directory_path(); diff --git a/test/v2/pid.cpp b/test/v2/pid.cpp index ae1841a9..aa77177f 100644 --- a/test/v2/pid.cpp +++ b/test/v2/pid.cpp @@ -18,6 +18,9 @@ BOOST_AUTO_TEST_CASE(test_pid) auto all = bp2::all_pids(); auto itr = std::find(all.begin(), all.end(), bp2::current_pid()); + +#if !defined(__APPLE___) && !defined(__MACH__) + BOOST_CHECK_GT(all.size(), 0u); BOOST_CHECK(itr != all.end()); std::vector children, grand_children; @@ -36,4 +39,6 @@ BOOST_AUTO_TEST_CASE(test_pid) return (!children.empty() || !grand_children.empty()); }; BOOST_CHECK_NE(grand_child_pids(bp2::root_pid, children, grand_children), false); +#endif + } diff --git a/test/v2/process.cpp b/test/v2/process.cpp index 703e820e..5a98a9a1 100644 --- a/test/v2/process.cpp +++ b/test/v2/process.cpp @@ -221,6 +221,8 @@ BOOST_AUTO_TEST_CASE(print_args_out) bpv::error_code ec; auto sz = asio::read(rp, st, ec); + while (ec == asio::error::interrupted) + sz += asio::read(rp, st, ec); BOOST_CHECK_NE(sz, 0u); BOOST_CHECK_MESSAGE((ec == asio::error::broken_pipe) || (ec == asio::error::eof), ec.message()); @@ -267,6 +269,8 @@ BOOST_AUTO_TEST_CASE(print_args_err) bpv::error_code ec; auto sz = asio::read(rp, st, ec); + while (ec == asio::error::interrupted) + sz += asio::read(rp, st, ec); BOOST_CHECK_NE(sz , 0u); BOOST_CHECK_MESSAGE((ec == asio::error::broken_pipe) || (ec == asio::error::eof), ec.message()); @@ -320,6 +324,9 @@ BOOST_AUTO_TEST_CASE(echo_file) bpv::error_code ec; auto sz = asio::read(rp, asio::dynamic_buffer(out), ec); + while (ec == asio::error::interrupted) + sz += asio::read(rp, asio::dynamic_buffer(out), ec); + BOOST_CHECK(sz != 0); BOOST_CHECK_MESSAGE((ec == asio::error::broken_pipe) || (ec == asio::error::eof), ec.message()); BOOST_CHECK_MESSAGE(out == test_data, out); @@ -344,6 +351,9 @@ BOOST_AUTO_TEST_CASE(print_same_cwd) bpv::error_code ec; auto sz = asio::read(rp, asio::dynamic_buffer(out), ec); + while (ec == asio::error::interrupted) + sz += asio::read(rp, asio::dynamic_buffer(out), ec); + BOOST_CHECK(sz != 0); BOOST_CHECK_MESSAGE((ec == asio::error::broken_pipe) || (ec == asio::error::eof), ec.message()); BOOST_CHECK_MESSAGE(bpv::filesystem::path(out) == bpv::filesystem::current_path(), @@ -373,6 +383,9 @@ BOOST_AUTO_TEST_CASE(popen) std::string res; boost::system::error_code ec; std::size_t n = asio::read(proc, asio::dynamic_buffer(res), ec); + while (ec == asio::error::interrupted) + n += asio::read(rp, asio::dynamic_buffer(res), ec); + BOOST_CHECK_MESSAGE(ec == asio::error::eof || ec == asio::error::broken_pipe, ec.message()); BOOST_REQUIRE_GE(n, 1u); // remove EOF @@ -406,6 +419,9 @@ BOOST_AUTO_TEST_CASE(print_other_cwd) bpv::error_code ec; auto sz = asio::read(rp, asio::dynamic_buffer(out), ec); + while (ec == asio::error::interrupted) + sz += asio::read(rp, asio::dynamic_buffer(out), ec); + BOOST_CHECK(sz != 0); BOOST_CHECK_MESSAGE((ec == asio::error::broken_pipe) || (ec == asio::error::eof), ec.message()); BOOST_CHECK_MESSAGE(bpv::filesystem::path(out) == target, @@ -436,7 +452,7 @@ std::string read_env(const char * name, Inits && ... inits) std::string out; bpv::error_code ec; - auto sz = asio::read(rp, asio::dynamic_buffer(out), ec); + auto sz = asio::read(rp, asio::dynamic_buffer(out), ec); while (ec == asio::error::interrupted) sz += asio::read(rp, asio::dynamic_buffer(out), ec); @@ -534,6 +550,7 @@ BOOST_AUTO_TEST_CASE(bind_launcher) auto sz = asio::read(rp, asio::dynamic_buffer(out), ec); while (ec == asio::error::interrupted) sz += asio::read(rp, asio::dynamic_buffer(out), ec); + BOOST_CHECK(sz != 0); BOOST_CHECK_MESSAGE((ec == asio::error::broken_pipe) || (ec == asio::error::eof), ec.message()); BOOST_CHECK_MESSAGE(bpv::filesystem::path(out) == target,