From ba7e8db9bb0e75ceafa8d2744a5156a0924b3956 Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Fri, 11 Nov 2022 11:14:46 +0800 Subject: [PATCH 01/27] Include fixes. --- include/boost/process/v2/detail/config.hpp | 4 ++-- include/boost/process/v2/posix/bind_fd.hpp | 1 + include/boost/process/v2/start_dir.hpp | 1 + include/boost/process/v2/stdio.hpp | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/boost/process/v2/detail/config.hpp b/include/boost/process/v2/detail/config.hpp index 981fe003..4febb8ca 100644 --- a/include/boost/process/v2/detail/config.hpp +++ b/include/boost/process/v2/detail/config.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #if defined(ASIO_WINDOWS) #define BOOST_PROCESS_V2_WINDOWS 1 @@ -51,6 +52,7 @@ #include #include #include +#include #if defined(BOOST_WINDOWS_API) #define BOOST_PROCESS_V2_WINDOWS 1 @@ -72,11 +74,9 @@ #if defined(BOOST_PROCESS_USE_STD_FS) #include -#include #else #include #include -#include #endif #define BOOST_PROCESS_V2_BEGIN_NAMESPACE namespace boost { namespace process { namespace v2 { diff --git a/include/boost/process/v2/posix/bind_fd.hpp b/include/boost/process/v2/posix/bind_fd.hpp index 6b46e236..dcdb64b9 100644 --- a/include/boost/process/v2/posix/bind_fd.hpp +++ b/include/boost/process/v2/posix/bind_fd.hpp @@ -94,6 +94,7 @@ struct bind_fd error_code on_setup(posix::default_launcher & launcher, const filesystem::path &, const char * const *) { launcher.fd_whitelist.push_back(target); + return {}; } /// Implementation of the initialization function. diff --git a/include/boost/process/v2/start_dir.hpp b/include/boost/process/v2/start_dir.hpp index 1410d7a2..c852b6cd 100644 --- a/include/boost/process/v2/start_dir.hpp +++ b/include/boost/process/v2/start_dir.hpp @@ -11,6 +11,7 @@ #define BOOST_PROCESS_v2_START_DIR_HPP #include +#include #include BOOST_PROCESS_V2_BEGIN_NAMESPACE diff --git a/include/boost/process/v2/stdio.hpp b/include/boost/process/v2/stdio.hpp index 000ffe62..df373afc 100644 --- a/include/boost/process/v2/stdio.hpp +++ b/include/boost/process/v2/stdio.hpp @@ -11,6 +11,7 @@ #define BOOST_PROCESS_V2_STDIO_HPP #include +#include #include #include #if defined(BOOST_PROCESS_V2_STANDALONE) From 3258e3a11c3a9494d546b3a6f79b124ffde47b67 Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Tue, 13 Dec 2022 09:19:45 +0800 Subject: [PATCH 02/27] Typo fix. --- doc/v2/quickstart.qbk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/v2/quickstart.qbk b/doc/v2/quickstart.qbk index 73ef4338..65b07fe8 100644 --- a/doc/v2/quickstart.qbk +++ b/doc/v2/quickstart.qbk @@ -1,4 +1,4 @@ -[section:quickstart Quickstrat] +[section:quickstart Quickstart] A process needs four things to be launched: From 32a2c2297cb98f20a50a3567fafd31a0502386bf Mon Sep 17 00:00:00 2001 From: sdarwin Date: Fri, 5 Nov 2021 13:10:45 -0500 Subject: [PATCH 03/27] Update metadata --- meta/libraries.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta/libraries.json b/meta/libraries.json index fe334e60..aaac0fa1 100644 --- a/meta/libraries.json +++ b/meta/libraries.json @@ -1,6 +1,6 @@ { "key": "process", - "name": "process", + "name": "Process", "authors": [ "Merino Vidal", "Ilya Sokolov", "Felipe Tanus", "Jeff Flinn", "Thomas Jarosch", "Boris Schaeling", "Klemens D. Morgenstern" From f12bc25122faa4c6b793e3d6d771f62902f48cde Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Tue, 13 Dec 2022 10:41:44 +0800 Subject: [PATCH 04/27] Disabled some tests for freebsd & added interrupt handling to osx test. --- test/Jamfile.jam | 2 +- test/v2/process.cpp | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/test/Jamfile.jam b/test/Jamfile.jam index e4d8273c..5da375b9 100644 --- a/test/Jamfile.jam +++ b/test/Jamfile.jam @@ -100,7 +100,7 @@ test-suite with-valgrind : [ 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 : no windows:yes BOOST_USE_WINDOWS_H=1 : group-windows-h ] - [ run group_wait.cpp system thread filesystem : [ test-options group_wait ] : sparring_partner : darwin:no ] + [ run group_wait.cpp system thread filesystem : [ test-options group_wait ] : sparring_partner : darwin:no freebsd:no ] [ run limit_fd.cpp program_options system filesystem : [ test-options limit_fd ] : sparring_partner : freebsd:no ] [ run run_exe.cpp filesystem : : sparring_partner ] [ run run_exe_path.cpp filesystem : [ test-options run_exe_path ] : sparring_partner ] diff --git a/test/v2/process.cpp b/test/v2/process.cpp index f0580cb4..77707656 100644 --- a/test/v2/process.cpp +++ b/test/v2/process.cpp @@ -434,7 +434,10 @@ std::string read_env(const char * name, Inits && ... inits) std::string out; bpv::error_code ec; - const 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); + BOOST_CHECK_MESSAGE((ec == asio::error::broken_pipe) || (ec == asio::error::eof), ec.message()); out.resize(sz); trim_end(out); From 765650aed32b3f767e944065c8d8fcfd30f01f03 Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Tue, 13 Dec 2022 13:50:03 +0800 Subject: [PATCH 05/27] Update process.cpp --- test/v2/process.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/v2/process.cpp b/test/v2/process.cpp index 77707656..e1c142c0 100644 --- a/test/v2/process.cpp +++ b/test/v2/process.cpp @@ -530,6 +530,8 @@ BOOST_AUTO_TEST_CASE(bind_launcher) 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, From d7df60938e14c12bef1bf8d2970f1c5ce9f33522 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Sun, 1 Jan 2023 14:49:13 +0200 Subject: [PATCH 06/27] Fix crash on search_path on Windows when PATHEXT is not found --- include/boost/process/detail/windows/search_path.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/process/detail/windows/search_path.hpp b/include/boost/process/detail/windows/search_path.hpp index 68172212..1aa0b813 100644 --- a/include/boost/process/detail/windows/search_path.hpp +++ b/include/boost/process/detail/windows/search_path.hpp @@ -35,7 +35,9 @@ inline boost::process::filesystem::path search_path( [&](const value_type & e) {return id == ::boost::to_upper_copy(e.get_name(), ::boost::process::detail::process_locale());}); - auto extensions_in = itr->to_vector(); + std::vector extensions_in; + if (itr != ne.cend()) + extensions_in = itr->to_vector(); std::vector extensions((extensions_in.size() * 2) + 1); From dc915be11d85dcfecbf037201d705da60ae7b7c0 Mon Sep 17 00:00:00 2001 From: Klemens Date: Sat, 24 Dec 2022 11:17:00 +0800 Subject: [PATCH 07/27] ec fix for search_path with std::filesystem. closes #287. --- include/boost/process/detail/posix/search_path.hpp | 4 ++++ include/boost/process/detail/windows/search_path.hpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/include/boost/process/detail/posix/search_path.hpp b/include/boost/process/detail/posix/search_path.hpp index e06f4163..b409642a 100644 --- a/include/boost/process/detail/posix/search_path.hpp +++ b/include/boost/process/detail/posix/search_path.hpp @@ -27,7 +27,11 @@ inline boost::process::filesystem::path search_path( for (const boost::process::filesystem::path & pp : path) { auto p = pp / filename; +#if defined(BOOST_PROCESS_USE_STD_FS) + std::error_code ec; +#else boost::system::error_code ec; +#endif bool file = boost::process::filesystem::is_regular_file(p, ec); if (!ec && file && ::access(p.c_str(), X_OK) == 0) return p; diff --git a/include/boost/process/detail/windows/search_path.hpp b/include/boost/process/detail/windows/search_path.hpp index 1aa0b813..5817a304 100644 --- a/include/boost/process/detail/windows/search_path.hpp +++ b/include/boost/process/detail/windows/search_path.hpp @@ -63,7 +63,11 @@ inline boost::process::filesystem::path search_path( { boost::process::filesystem::path pp_ext = p; pp_ext += ext; +#if defined(BOOST_PROCESS_USE_STD_FS) + std::error_code ec; +#else boost::system::error_code ec; +#endif bool file = boost::process::filesystem::is_regular_file(pp_ext, ec); if (!ec && file && ::boost::winapi::sh_get_file_info(pp_ext.native().c_str(), 0, 0, 0, ::boost::winapi::SHGFI_EXETYPE_)) From 1dc9d8689e3e9a62129f3c5b36484cd10242eec7 Mon Sep 17 00:00:00 2001 From: Gary Miguel Date: Wed, 28 Dec 2022 19:09:47 -0800 Subject: [PATCH 08/27] fix error message --- include/boost/process/v2/src.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/process/v2/src.hpp b/include/boost/process/v2/src.hpp index 7bf38448..9c3b3fb7 100644 --- a/include/boost/process/v2/src.hpp +++ b/include/boost/process/v2/src.hpp @@ -10,7 +10,7 @@ #include #if defined(BOOST_PROCESS_V2_HEADER_ONLY) -# error Do not compile Beast library source with BOOST_BEAST_HEADER_ONLY defined +# error Do not compile Process V2 library source with BOOST_PROCESS_V2_HEADER_ONLY defined. You should probably define BOOST_PROCESS_V2_SEPARATE_COMPILATION #endif #include From 5fcf5465cee6566be79fa3b152f0c04eba216ae0 Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Mon, 6 Feb 2023 20:01:15 +0800 Subject: [PATCH 09/27] Switched vector in list of sigclhd_service. Closes #175 --- include/boost/process/detail/posix/sigchld_service.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/process/detail/posix/sigchld_service.hpp b/include/boost/process/detail/posix/sigchld_service.hpp index 7e92f569..4eb6de6c 100644 --- a/include/boost/process/detail/posix/sigchld_service.hpp +++ b/include/boost/process/detail/posix/sigchld_service.hpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace boost { namespace process { namespace detail { namespace posix { @@ -23,7 +24,7 @@ class sigchld_service : public boost::asio::detail::service_base _strand{get_io_context().get_executor()}; boost::asio::signal_set _signal_set{get_io_context(), SIGCHLD}; - std::vector>> _receivers; + std::list>> _receivers; inline void _handle_signal(const boost::system::error_code & ec); public: sigchld_service(boost::asio::io_context & io_context) From 0fdd448c67054632af5353189da14f3eaaafb6e3 Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Mon, 6 Feb 2023 20:05:09 +0800 Subject: [PATCH 10/27] Deprecated wait_for & wait_until. --- include/boost/process/detail/child_decl.hpp | 10 +++++++++- include/boost/process/detail/config.hpp | 21 ++++++++++++++++++++- include/boost/process/group.hpp | 7 ++++++- test/extensions.cpp | 1 - 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/include/boost/process/detail/child_decl.hpp b/include/boost/process/detail/child_decl.hpp index 3dcb777a..5540403f 100644 --- a/include/boost/process/detail/child_decl.hpp +++ b/include/boost/process/detail/child_decl.hpp @@ -125,7 +125,10 @@ public: boost::process::detail::throw_error(ec, "wait error"); } +#if !defined(BOOST_PROCESS_NO_DEPRECATED) + template< class Rep, class Period > + BOOST_PROCESS_DEPRECATED("wait_for is unreliable") bool wait_for (const std::chrono::duration& rel_time) { std::error_code ec; @@ -135,6 +138,7 @@ public: } template< class Clock, class Duration > + BOOST_PROCESS_DEPRECATED("wait_until is unreliable") bool wait_until(const std::chrono::time_point& timeout_time ) { std::error_code ec; @@ -142,6 +146,7 @@ public: boost::process::detail::throw_error(ec, "wait_until error"); return b; } +#endif bool running(std::error_code & ec) noexcept { @@ -178,13 +183,16 @@ public: } } +#if !defined(BOOST_PROCESS_NO_DEPRECATED) template< class Rep, class Period > + BOOST_PROCESS_DEPRECATED("wait_for is unreliable") bool wait_for (const std::chrono::duration& rel_time, std::error_code & ec) noexcept { return wait_until(std::chrono::steady_clock::now() + rel_time, ec); } template< class Clock, class Duration > + BOOST_PROCESS_DEPRECATED("wait_until is unreliable") bool wait_until(const std::chrono::time_point& timeout_time, std::error_code & ec) noexcept { if (!_exited()) @@ -197,7 +205,7 @@ public: } return true; } - +#endif bool valid() const { diff --git a/include/boost/process/detail/config.hpp b/include/boost/process/detail/config.hpp index 55ca0817..36d89819 100644 --- a/include/boost/process/detail/config.hpp +++ b/include/boost/process/detail/config.hpp @@ -114,6 +114,25 @@ template constexpr Char space_sign(); template<> constexpr char space_sign () {return ' '; } template<> constexpr wchar_t space_sign () {return L' '; } +} +} +} + + +#if defined(__clang__) +# define BOOST_PROCESS_DEPRECATED(msg) __attribute__((deprecated(msg))) +#elif defined(__GNUC__) +# if __GNUC__ * 100 + __GNUC_MINOR__ >= 405 +# define BOOST_PROCESS_DEPRECATED(msg) __attribute__((deprecated(msg))) +# else +# define BOOST_PROCESS_DEPRECATED(msg) __attribute__((deprecated)) +# endif +#elif defined(_MSC_VER) +# define BOOST_PROCESS_DEPRECATED(msg) __declspec(deprecated(msg)) +#elif defined(__sun) +# define BOOST_PROCESS_DEPRECATED(msg) __attribute__((deprecated(msg))) +#else +# define BOOST_PROCESS_DEPRECATED(msg) +#endif -}}} #endif diff --git a/include/boost/process/group.hpp b/include/boost/process/group.hpp index b46f0644..ff219203 100644 --- a/include/boost/process/group.hpp +++ b/include/boost/process/group.hpp @@ -122,9 +122,11 @@ public: { boost::process::detail::api::wait(_group_handle, ec); } +#if !defined(BOOST_PROCESS_NO_DEPRECATED) /** Wait for the process group to exit for period of time. * \return True if all child processes exited while waiting.*/ template< class Rep, class Period > + BOOST_PROCESS_DEPRECATED("wait_for is unreliable") bool wait_for (const std::chrono::duration& rel_time) { return boost::process::detail::api::wait_for(_group_handle, rel_time); @@ -132,6 +134,7 @@ public: /** \overload bool wait_for(const std::chrono::duration& timeout_time ) */ template< class Rep, class Period > + BOOST_PROCESS_DEPRECATED("wait_for is unreliable") bool wait_for (const std::chrono::duration& rel_time, std::error_code & ec) noexcept { return boost::process::detail::api::wait_for(_group_handle, rel_time, ec); @@ -140,17 +143,19 @@ public: /** Wait for the process group to exit until a point in time. * \return True if all child processes exited while waiting.*/ template< class Clock, class Duration > + BOOST_PROCESS_DEPRECATED("wait_until is unreliable") bool wait_until(const std::chrono::time_point& timeout_time ) { return boost::process::detail::api::wait_until(_group_handle, timeout_time); } /** \overload bool wait_until(const std::chrono::time_point& timeout_time ) */ template< class Clock, class Duration > + BOOST_PROCESS_DEPRECATED("wait_until is unreliable") bool wait_until(const std::chrono::time_point& timeout_time, std::error_code & ec) noexcept { return boost::process::detail::api::wait_until(_group_handle, timeout_time, ec); } - +#endif ///Check if the group has a valid handle. bool valid() const { diff --git a/test/extensions.cpp b/test/extensions.cpp index f7374d25..2f16dc3b 100644 --- a/test/extensions.cpp +++ b/test/extensions.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include From bc9a98787e899a1e82d49889f2a87b8ef513409a Mon Sep 17 00:00:00 2001 From: Ivan Efimov Date: Mon, 31 Jan 2022 23:46:08 +0300 Subject: [PATCH 11/27] Fix string construction in native_environment_impl::get --- include/boost/process/detail/windows/environment.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/process/detail/windows/environment.hpp b/include/boost/process/detail/windows/environment.hpp index 53408ac7..79ed6a07 100644 --- a/include/boost/process/detail/windows/environment.hpp +++ b/include/boost/process/detail/windows/environment.hpp @@ -90,12 +90,12 @@ inline auto native_environment_impl::get(const pointer_type id) -> string_ ::boost::process::detail::throw_last_error("GetEnvironmentVariable() failed"); else return std::basic_string( - buf.data(), buf.data()+ size + 1); + buf.data(), buf.data()+ size); } } - return std::basic_string(buf, buf+size+1); + return std::basic_string(buf, buf+size); } template From 744e9d95b3b03e6cbc585cff83be7434334f231a Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Mon, 6 Feb 2023 20:08:21 +0800 Subject: [PATCH 12/27] [drone] Removed mlocate dep. --- .drone.star | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.drone.star b/.drone.star index 6ab86ef2..03fb41f2 100644 --- a/.drone.star +++ b/.drone.star @@ -16,16 +16,16 @@ def main(ctx): return [ freebsd_cxx("gcc 11 freebsd", "g++-11", buildtype="boost", buildscript="drone", freebsd_version="13.1", environment={'B2_TOOLSET': 'gcc-11', 'B2_CXXSTD': '17,20', 'B2_LINKFLAGS': '-Wl,-rpath=/usr/local/lib/gcc11'}, globalenv=globalenv), freebsd_cxx("clang 14 freebsd", "clang++-14", buildtype="boost", buildscript="drone", freebsd_version="13.1", environment={'B2_TOOLSET': 'clang-14', 'B2_CXXSTD': '17,20'}, globalenv=globalenv), - linux_cxx("docs", "", packages="docbook docbook-xml docbook-xsl xsltproc libsaxonhe-java default-jre-headless flex libfl-dev bison unzip rsync mlocate", image="cppalliance/droneubuntu1804:1", buildtype="docs", buildscript="drone", environment={"COMMENT": "docs"}, globalenv=globalenv), + linux_cxx("docs", "", packages="docbook docbook-xml docbook-xsl xsltproc libsaxonhe-java default-jre-headless flex libfl-dev bison unzip rsync", image="cppalliance/droneubuntu1804:1", buildtype="docs", buildscript="drone", environment={"COMMENT": "docs"}, globalenv=globalenv), linux_cxx("asan", "g++-8", packages="g++-8", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'COMMENT': 'asan', 'B2_VARIANT': 'debug', 'B2_TOOLSET': 'gcc-8', 'B2_CXXSTD': '11', 'B2_ASAN': '1', 'B2_DEFINES': 'BOOST_NO_STRESS_TEST=1', 'DRONE_EXTRA_PRIVILEGED': 'True', 'DRONE_JOB_UUID': '356a192b79'}, globalenv=globalenv, privileged=True), linux_cxx("ubsan", "g++-8", packages="g++-8", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'COMMENT': 'ubsan', 'B2_VARIANT': 'debug', 'B2_TOOLSET': 'gcc-8', 'B2_CXXSTD': '11', 'B2_UBSAN': '1', 'B2_DEFINES': 'BOOST_NO_STRESS_TEST=1', 'B2_LINKFLAGS': '-fuse-ld=gold', 'DRONE_JOB_UUID': '77de68daec'}, globalenv=globalenv), linux_cxx("gcc 11 arm64", "g++-11", packages="g++-11", buildtype="boost", buildscript="drone", image="cppalliance/droneubuntu2004:multiarch", environment={ 'B2_TOOLSET': 'gcc-11', 'B2_CXXSTD': '11', 'DRONE_JOB_UUID': '17ba079169m'}, arch="arm64", globalenv=globalenv), - linux_cxx("GCC 10, Debug + Coverage", "g++-10", packages="g++-10 libssl-dev libffi-dev binutils-gold gdb mlocate", + linux_cxx("GCC 10, Debug + Coverage", "g++-10", packages="g++-10 libssl-dev libffi-dev binutils-gold gdb", image="cppalliance/droneubuntu2004:1", buildtype="boost", buildscript="drone", environment={"GCOV": "gcov-10", "LCOV_VERSION": "1.15", "VARIANT": "process_coverage", "TOOLSET": "gcc", "COMPILER": "g++-10", "CXXSTD": "11", "DRONE_BEFORE_INSTALL" : "process_coverage", "CODECOV_TOKEN": {"from_secret": "codecov_token"}}, globalenv=globalenv, privileged=True), # A set of jobs based on the earlier .travis.yml configuration: - linux_cxx("Default clang++ with libc++", "clang++-libc++", packages="libc++-dev mlocate", image="cppalliance/droneubuntu1604:1", buildtype="buildtype", buildscript="drone", environment={ "B2_TOOLSET": "clang-7", "B2_CXXSTD": "11", "VARIANT": "debug", "TOOLSET": "clang", "COMPILER": "clang++-libc++", "CXXSTD": "11", "CXX_FLAGS": "-stdlib=libc++ -stdlib=libc++", "TRAVISCLANG" : "yes" }, globalenv=globalenv), - linux_cxx("Default g++", "g++", packages="mlocate", image="cppalliance/droneubuntu1604:1", buildtype="buildtype", buildscript="drone", environment={ "VARIANT": "release", "TOOLSET": "gcc", "COMPILER": "g++", "CXXSTD": "11" }, globalenv=globalenv), - linux_cxx("Clang 3.8, UBasan", "clang++-3.8", packages="clang-3.8 libssl-dev mlocate", llvm_os="precise", llvm_ver="3.8", image="cppalliance/droneubuntu1604:1", buildtype="boost", buildscript="drone", environment={"VARIANT": "process_ubasan", "TOOLSET": "clang", "COMPILER": "clang++-3.8", "CXXSTD": "11", "UBSAN_OPTIONS": 'print_stacktrace=1', "DRONE_BEFORE_INSTALL": "UBasan" }, globalenv=globalenv), + linux_cxx("Default clang++ with libc++", "clang++-libc++", packages="libc++-dev", image="cppalliance/droneubuntu1604:1", buildtype="buildtype", buildscript="drone", environment={ "B2_TOOLSET": "clang-7", "B2_CXXSTD": "11", "VARIANT": "debug", "TOOLSET": "clang", "COMPILER": "clang++-libc++", "CXXSTD": "11", "CXX_FLAGS": "-stdlib=libc++ -stdlib=libc++", "TRAVISCLANG" : "yes" }, globalenv=globalenv), + linux_cxx("Default g++", "g++", image="cppalliance/droneubuntu1604:1", buildtype="buildtype", buildscript="drone", environment={ "VARIANT": "release", "TOOLSET": "gcc", "COMPILER": "g++", "CXXSTD": "11" }, globalenv=globalenv), + linux_cxx("Clang 3.8, UBasan", "clang++-3.8", packages="clang-3.8 libssl-dev", llvm_os="precise", llvm_ver="3.8", image="cppalliance/droneubuntu1604:1", buildtype="boost", buildscript="drone", environment={"VARIANT": "process_ubasan", "TOOLSET": "clang", "COMPILER": "clang++-3.8", "CXXSTD": "11", "UBSAN_OPTIONS": 'print_stacktrace=1', "DRONE_BEFORE_INSTALL": "UBasan" }, globalenv=globalenv), linux_cxx("gcc 6", "g++-6", packages="g++-6", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'B2_TOOLSET': 'gcc-6', 'B2_CXXSTD': '11', 'DRONE_JOB_UUID': '902ba3cda1'}, globalenv=globalenv), linux_cxx("clang 3.8", "clang++-3.8", packages="clang-3.8", buildtype="boost", buildscript="drone", image="cppalliance/droneubuntu1604:1", environment={'B2_TOOLSET': 'clang', 'COMPILER': 'clang++-3.8', 'B2_CXXSTD': '11', 'DRONE_JOB_UUID': '7b52009b64'}, globalenv=globalenv), osx_cxx("clang", "g++", packages="", buildtype="boost", buildscript="drone", environment={'B2_TOOLSET': 'clang', 'B2_CXXSTD': '11,17', 'DRONE_JOB_UUID': '91032ad7bb'}, globalenv=globalenv), From bbc7eb82e5b47d712e4f07e3c358a1f5e1e094d6 Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Mon, 6 Feb 2023 20:10:28 +0800 Subject: [PATCH 13/27] disabled terminate test for freebsd. --- test/Jamfile.jam | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Jamfile.jam b/test/Jamfile.jam index 5da375b9..dd875514 100644 --- a/test/Jamfile.jam +++ b/test/Jamfile.jam @@ -111,7 +111,7 @@ test-suite with-valgrind : [ 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 terminate.cpp system filesystem : [ test-options terminate ] : sparring_partner : freebsd:no ] [ 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 ] From 57b67e0173a9dda42b7aeef15b179f4c7ccf0a54 Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Mon, 6 Feb 2023 20:17:14 +0800 Subject: [PATCH 14/27] added clang 3.8. noexcept deduction. --- include/boost/process/v2/environment.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/process/v2/environment.hpp b/include/boost/process/v2/environment.hpp index 2814d1f5..6309de88 100644 --- a/include/boost/process/v2/environment.hpp +++ b/include/boost/process/v2/environment.hpp @@ -524,7 +524,7 @@ struct key ~key() = default; key& operator=( const key& p ) = default; - key& operator=( key&& p ) noexcept = default; + key& operator=( key&& p ) noexcept(std::is_nothrow_move_constructible::value) = default; key& operator=( string_type&& source ) { value_ = std::move(source); @@ -742,7 +742,7 @@ struct value ~value() = default; value& operator=( const value& p ) = default; - value& operator=( value&& p ) noexcept = default; + value& operator=( value&& p ) noexcept(std::is_nothrow_move_constructible::value) = default; value& operator=( string_type&& source ) { value_ = std::move(source); @@ -999,7 +999,7 @@ struct key_value_pair ~key_value_pair() = default; key_value_pair& operator=( const key_value_pair& p ) = default; - key_value_pair& operator=( key_value_pair&& p ) noexcept = default; + key_value_pair& operator=( key_value_pair&& p ) noexcept(std::is_nothrow_move_constructible::value) = default; key_value_pair& operator=( string_type&& source ) { value_ = std::move(source); From 6f0d6a2e243788d881786d1ae86b40ace1bee454 Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Mon, 6 Feb 2023 20:33:50 +0800 Subject: [PATCH 15/27] switched to BOOST_DEPRECATED. --- include/boost/process/detail/child_decl.hpp | 8 ++++---- include/boost/process/detail/config.hpp | 17 ----------------- include/boost/process/group.hpp | 8 ++++---- 3 files changed, 8 insertions(+), 25 deletions(-) diff --git a/include/boost/process/detail/child_decl.hpp b/include/boost/process/detail/child_decl.hpp index 5540403f..452295a0 100644 --- a/include/boost/process/detail/child_decl.hpp +++ b/include/boost/process/detail/child_decl.hpp @@ -128,7 +128,7 @@ public: #if !defined(BOOST_PROCESS_NO_DEPRECATED) template< class Rep, class Period > - BOOST_PROCESS_DEPRECATED("wait_for is unreliable") + BOOST_DEPRECATED("wait_for is unreliable") bool wait_for (const std::chrono::duration& rel_time) { std::error_code ec; @@ -138,7 +138,7 @@ public: } template< class Clock, class Duration > - BOOST_PROCESS_DEPRECATED("wait_until is unreliable") + BOOST_DEPRECATED("wait_until is unreliable") bool wait_until(const std::chrono::time_point& timeout_time ) { std::error_code ec; @@ -185,14 +185,14 @@ public: #if !defined(BOOST_PROCESS_NO_DEPRECATED) template< class Rep, class Period > - BOOST_PROCESS_DEPRECATED("wait_for is unreliable") + BOOST_DEPRECATED("wait_for is unreliable") bool wait_for (const std::chrono::duration& rel_time, std::error_code & ec) noexcept { return wait_until(std::chrono::steady_clock::now() + rel_time, ec); } template< class Clock, class Duration > - BOOST_PROCESS_DEPRECATED("wait_until is unreliable") + BOOST_DEPRECATED("wait_until is unreliable") bool wait_until(const std::chrono::time_point& timeout_time, std::error_code & ec) noexcept { if (!_exited()) diff --git a/include/boost/process/detail/config.hpp b/include/boost/process/detail/config.hpp index 36d89819..646daa09 100644 --- a/include/boost/process/detail/config.hpp +++ b/include/boost/process/detail/config.hpp @@ -118,21 +118,4 @@ template<> constexpr wchar_t space_sign () {return L' '; } } } - -#if defined(__clang__) -# define BOOST_PROCESS_DEPRECATED(msg) __attribute__((deprecated(msg))) -#elif defined(__GNUC__) -# if __GNUC__ * 100 + __GNUC_MINOR__ >= 405 -# define BOOST_PROCESS_DEPRECATED(msg) __attribute__((deprecated(msg))) -# else -# define BOOST_PROCESS_DEPRECATED(msg) __attribute__((deprecated)) -# endif -#elif defined(_MSC_VER) -# define BOOST_PROCESS_DEPRECATED(msg) __declspec(deprecated(msg)) -#elif defined(__sun) -# define BOOST_PROCESS_DEPRECATED(msg) __attribute__((deprecated(msg))) -#else -# define BOOST_PROCESS_DEPRECATED(msg) -#endif - #endif diff --git a/include/boost/process/group.hpp b/include/boost/process/group.hpp index ff219203..7487f86f 100644 --- a/include/boost/process/group.hpp +++ b/include/boost/process/group.hpp @@ -126,7 +126,7 @@ public: /** Wait for the process group to exit for period of time. * \return True if all child processes exited while waiting.*/ template< class Rep, class Period > - BOOST_PROCESS_DEPRECATED("wait_for is unreliable") + BOOST_DEPRECATED("wait_for is unreliable") bool wait_for (const std::chrono::duration& rel_time) { return boost::process::detail::api::wait_for(_group_handle, rel_time); @@ -134,7 +134,7 @@ public: /** \overload bool wait_for(const std::chrono::duration& timeout_time ) */ template< class Rep, class Period > - BOOST_PROCESS_DEPRECATED("wait_for is unreliable") + BOOST_DEPRECATED("wait_for is unreliable") bool wait_for (const std::chrono::duration& rel_time, std::error_code & ec) noexcept { return boost::process::detail::api::wait_for(_group_handle, rel_time, ec); @@ -143,14 +143,14 @@ public: /** Wait for the process group to exit until a point in time. * \return True if all child processes exited while waiting.*/ template< class Clock, class Duration > - BOOST_PROCESS_DEPRECATED("wait_until is unreliable") + BOOST_DEPRECATED("wait_until is unreliable") bool wait_until(const std::chrono::time_point& timeout_time ) { return boost::process::detail::api::wait_until(_group_handle, timeout_time); } /** \overload bool wait_until(const std::chrono::time_point& timeout_time ) */ template< class Clock, class Duration > - BOOST_PROCESS_DEPRECATED("wait_until is unreliable") + BOOST_DEPRECATED("wait_until is unreliable") bool wait_until(const std::chrono::time_point& timeout_time, std::error_code & ec) noexcept { return boost::process::detail::api::wait_until(_group_handle, timeout_time, ec); From f1302430cb3d37001ff3d575c2bc3d78239df8be Mon Sep 17 00:00:00 2001 From: Samuel Venable Date: Mon, 6 Feb 2023 20:43:32 +0800 Subject: [PATCH 16/27] extern process management. --- .gitignore | 1 + .../process/v2/detail/environment_posix.hpp | 4 +- .../v2/detail/impl/process_handle_windows.ipp | 56 +- .../process/v2/detail/process_handle_fd.hpp | 37 + .../v2/detail/process_handle_fd_or_signal.hpp | 37 + .../v2/detail/process_handle_signal.hpp | 59 +- .../v2/detail/process_handle_windows.hpp | 28 + include/boost/process/v2/ext/cmd.hpp | 55 ++ include/boost/process/v2/ext/cwd.hpp | 47 ++ .../process/v2/ext/detail/impl/proc_info.ipp | 127 +++ .../boost/process/v2/ext/detail/proc_info.hpp | 125 +++ include/boost/process/v2/ext/env.hpp | 138 ++++ include/boost/process/v2/ext/exe.hpp | 49 ++ include/boost/process/v2/ext/impl/cmd.ipp | 468 +++++++++++ include/boost/process/v2/ext/impl/cwd.ipp | 234 ++++++ include/boost/process/v2/ext/impl/env.ipp | 295 +++++++ include/boost/process/v2/ext/impl/exe.ipp | 192 +++++ include/boost/process/v2/impl/pid.ipp | 739 +++++++++++++++++- include/boost/process/v2/impl/shell.ipp | 22 +- include/boost/process/v2/pid.hpp | 29 +- include/boost/process/v2/process.hpp | 34 +- include/boost/process/v2/shell.hpp | 18 +- include/boost/process/v2/src.hpp | 5 + test/v2/CMakeLists.txt | 9 +- test/v2/Jamfile.jam | 8 + test/v2/ext.cpp | 173 ++++ test/v2/pid.cpp | 26 +- test/v2/process.cpp | 2 + 28 files changed, 2974 insertions(+), 43 deletions(-) create mode 100644 include/boost/process/v2/ext/cmd.hpp create mode 100644 include/boost/process/v2/ext/cwd.hpp create mode 100644 include/boost/process/v2/ext/detail/impl/proc_info.ipp create mode 100644 include/boost/process/v2/ext/detail/proc_info.hpp create mode 100644 include/boost/process/v2/ext/env.hpp create mode 100644 include/boost/process/v2/ext/exe.hpp create mode 100644 include/boost/process/v2/ext/impl/cmd.ipp create mode 100644 include/boost/process/v2/ext/impl/cwd.ipp create mode 100644 include/boost/process/v2/ext/impl/env.ipp create mode 100644 include/boost/process/v2/ext/impl/exe.ipp create mode 100644 test/v2/ext.cpp diff --git a/.gitignore b/.gitignore index 4354fdab..51166dfa 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,5 @@ /notes.cpp /notes_p.txt .settings +.DS_Store diff --git a/include/boost/process/v2/detail/environment_posix.hpp b/include/boost/process/v2/detail/environment_posix.hpp index 237a8739..e945a86c 100644 --- a/include/boost/process/v2/detail/environment_posix.hpp +++ b/include/boost/process/v2/detail/environment_posix.hpp @@ -14,7 +14,7 @@ #include #include -#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__APPLE__) || defined(__MACH__) +#if defined(__APPLE__) || defined(__MACH__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__sun) extern "C" { extern char **environ; } #endif @@ -77,4 +77,4 @@ BOOST_PROCESS_V2_DECL bool is_executable(const filesystem::path & pth, error_cod BOOST_PROCESS_V2_END_NAMESPACE -#endif \ No newline at end of file +#endif diff --git a/include/boost/process/v2/detail/impl/process_handle_windows.ipp b/include/boost/process/v2/detail/impl/process_handle_windows.ipp index 96422480..638bc014 100644 --- a/include/boost/process/v2/detail/impl/process_handle_windows.ipp +++ b/include/boost/process/v2/detail/impl/process_handle_windows.ipp @@ -9,9 +9,20 @@ #include #include #include +#include #include +#if !defined(BOOST_PROCESS_V2_DISABLE_UNDOCUMENTED_API) +extern "C" +{ + +LONG WINAPI NtResumeProcess(HANDLE ProcessHandle); +LONG WINAPI NtSuspendProcess(HANDLE ProcessHandle); + +} +#endif + BOOST_PROCESS_V2_BEGIN_NAMESPACE namespace detail @@ -40,10 +51,10 @@ void terminate_if_running_(HANDLE handle) { DWORD exit_code = 0u; if (handle == INVALID_HANDLE_VALUE) - return ; + return ; if (::GetExitCodeProcess(handle, &exit_code)) - if (exit_code == STILL_ACTIVE) - ::TerminateProcess(handle, 260); + if (exit_code == STILL_ACTIVE) + ::TerminateProcess(handle, 260); } bool check_handle_(HANDLE handle, error_code & ec) @@ -60,8 +71,8 @@ bool check_pid_(pid_type pid_, error_code & ec) { if (pid_ == 0) { - ec.assign(ERROR_INVALID_HANDLE_STATE, system_category()); - return false; + ec.assign(ERROR_INVALID_HANDLE_STATE, system_category()); + return false; } return true; } @@ -73,19 +84,19 @@ struct enum_windows_data_t }; static BOOL CALLBACK enum_window(HWND hwnd, LPARAM param) - { +{ auto data = reinterpret_cast(param); DWORD pid{0u}; GetWindowThreadProcessId(hwnd, &pid); if (pid != data->pid) - return TRUE; + return TRUE; LRESULT res = ::SendMessageW(hwnd, WM_CLOSE, 0, 0); if (res) - data->ec = detail::get_last_error(); + data->ec = detail::get_last_error(); return res == 0; - } +} void request_exit_(pid_type pid_, error_code & ec) { @@ -113,6 +124,33 @@ void check_running_(HANDLE handle, error_code & ec, DWORD & exit_status) ec = detail::get_last_error(); } +#if !defined(BOOST_PROCESS_V2_DISABLE_UNDOCUMENTED_API) +void suspend_(HANDLE handle, error_code & ec) +{ + auto nt_err = NtSuspendProcess(handle); + ULONG dos_err = RtlNtStatusToDosError(nt_err); + if (dos_err) + ec = detail::get_last_error(); +} + +void resume_(HANDLE handle, error_code & ec) +{ + auto nt_err = NtResumeProcess(handle); + ULONG dos_err = RtlNtStatusToDosError(nt_err); + if (dos_err) + ec = detail::get_last_error(); +} +#else +void suspend_(HANDLE, error_code & ec) +{ + ec.assign(ERROR_CALL_NOT_IMPLEMENTED, system_category()); +} + +void resume_(HANDLE handle, error_code & ec) +{ + ec.assign(ERROR_CALL_NOT_IMPLEMENTED, system_category()); +} +#endif #if !defined(BOOST_PROCESS_V2_HEADER_ONLY) template struct basic_process_handle_win<>; diff --git a/include/boost/process/v2/detail/process_handle_fd.hpp b/include/boost/process/v2/detail/process_handle_fd.hpp index 86854266..d3b198dd 100644 --- a/include/boost/process/v2/detail/process_handle_fd.hpp +++ b/include/boost/process/v2/detail/process_handle_fd.hpp @@ -101,6 +101,8 @@ struct basic_process_handle_fd pid_type id() const { return pid_; } + native_handle_type native_handle() {return pid_;} + void terminate_if_running(error_code &) { if (pid_ <= 0) @@ -182,7 +184,42 @@ struct basic_process_handle_fd if (ec) detail::throw_error(ec, "request_exit"); } + + void suspend() + { + if (pid_ <= 0) + return ; + error_code ec; + suspend(ec); + if (ec) + detail::throw_error(ec, "suspend"); + } + void suspend(error_code &ec) + { + if (pid_ <= 0) + return ; + if (::kill(pid_, SIGSTOP) == -1) + ec = get_last_error(); + } + + void resume() + { + if (pid_ <= 0) + return ; + error_code ec; + resume(ec); + if (ec) + detail::throw_error(ec, "resume"); + } + + void resume(error_code &ec) + { + if (pid_ <= 0) + return ; + if (::kill(pid_, SIGCONT) == -1) + ec = get_last_error(); + } void terminate(native_exit_code_type &exit_status, error_code &ec) { if (pid_ <= 0) diff --git a/include/boost/process/v2/detail/process_handle_fd_or_signal.hpp b/include/boost/process/v2/detail/process_handle_fd_or_signal.hpp index c91b3153..dfbee11f 100644 --- a/include/boost/process/v2/detail/process_handle_fd_or_signal.hpp +++ b/include/boost/process/v2/detail/process_handle_fd_or_signal.hpp @@ -128,6 +128,7 @@ struct basic_process_handle_fd_or_signal pid_type id() const { return pid_; } + native_handle_type native_handle() {return pid_;} void terminate_if_running(error_code &) { @@ -211,6 +212,42 @@ struct basic_process_handle_fd_or_signal if (ec) detail::throw_error(ec, "request_exit"); } + + void suspend() + { + if (pid_ <= 0) + return ; + error_code ec; + suspend(ec); + if (ec) + detail::throw_error(ec, "suspend"); + } + + void suspend(error_code &ec) + { + if (pid_ <= 0) + return ; + if (::kill(pid_, SIGSTOP) == -1) + ec = get_last_error(); + } + + void resume() + { + if (pid_ <= 0) + return ; + error_code ec; + resume(ec); + if (ec) + detail::throw_error(ec, "resume"); + } + + void resume(error_code &ec) + { + if (pid_ <= 0) + return ; + if (::kill(pid_, SIGCONT) == -1) + ec = get_last_error(); + } void terminate(native_exit_code_type &exit_status, error_code &ec) { diff --git a/include/boost/process/v2/detail/process_handle_signal.hpp b/include/boost/process/v2/detail/process_handle_signal.hpp index cf042c40..00f7bbcc 100644 --- a/include/boost/process/v2/detail/process_handle_signal.hpp +++ b/include/boost/process/v2/detail/process_handle_signal.hpp @@ -41,7 +41,7 @@ struct basic_process_handle_signal { native_handle_type() = delete; native_handle_type(const native_handle_type & ) = delete; - ~native_handle_type() = delete; + ~native_handle_type() = default; }; typedef Executor executor_type; @@ -103,6 +103,7 @@ struct basic_process_handle_signal pid_type id() const { return pid_; } + native_handle_type native_handle() {return pid_;} void terminate_if_running(error_code &) { @@ -112,7 +113,7 @@ struct basic_process_handle_signal void terminate_if_running() { if (pid_ <= 0) - return ; + return; if (::waitpid(pid_, nullptr, WNOHANG) == 0) { ::kill(pid_, SIGKILL); @@ -123,7 +124,7 @@ struct basic_process_handle_signal void wait(native_exit_code_type &exit_status, error_code &ec) { if (pid_ <= 0) - return ; + return; while (::waitpid(pid_, &exit_status, 0) < 0) { if (errno != EINTR) @@ -137,7 +138,7 @@ struct basic_process_handle_signal void wait(native_exit_code_type &exit_status) { if (pid_ <= 0) - return ; + return; error_code ec; wait(exit_status, ec); if (ec) @@ -147,7 +148,7 @@ struct basic_process_handle_signal void interrupt(error_code &ec) { if (pid_ <= 0) - return ; + return; if (::kill(pid_, SIGTERM) == -1) ec = get_last_error(); } @@ -155,7 +156,7 @@ struct basic_process_handle_signal void interrupt() { if (pid_ <= 0) - return ; + return; error_code ec; interrupt(ec); if (ec) @@ -165,7 +166,7 @@ struct basic_process_handle_signal void request_exit(error_code &ec) { if (pid_ <= 0) - return ; + return; if (::kill(pid_, SIGTERM) == -1) ec = get_last_error(); } @@ -173,17 +174,53 @@ struct basic_process_handle_signal void request_exit() { if (pid_ <= 0) - return ; + return; error_code ec; request_exit(ec); if (ec) detail::throw_error(ec, "request_exit"); } + void suspend() + { + if (pid_ <= 0) + return; + error_code ec; + suspend(ec); + if (ec) + detail::throw_error(ec, "suspend"); + } + + void suspend(error_code &ec) + { + if (pid_ <= 0) + return; + if (::kill(pid_, SIGCONT) == -1) + ec = get_last_error(); + } + + void resume() + { + if (pid_ <= 0) + return; + error_code ec; + resume(ec); + if (ec) + detail::throw_error(ec, "resume"); + } + + void resume(error_code &ec) + { + if (pid_ <= 0) + return; + if (::kill(pid_, SIGTERM) == -1) + ec = get_last_error(); + } + void terminate(native_exit_code_type &exit_status, error_code &ec) { if (pid_ <= 0) - return ; + return; if (::kill(pid_, SIGKILL) == -1) ec = get_last_error(); } @@ -191,7 +228,7 @@ struct basic_process_handle_signal void terminate(native_exit_code_type &exit_status) { if (pid_ <= 0) - return ; + return; error_code ec; terminate(exit_status, ec); if (ec) @@ -284,7 +321,7 @@ struct basic_process_handle_signal if (!ec && (wait_res == 0)) { handle.async_wait(std::move(self)); - return ; + return; } struct completer diff --git a/include/boost/process/v2/detail/process_handle_windows.hpp b/include/boost/process/v2/detail/process_handle_windows.hpp index 275d0551..979536a5 100644 --- a/include/boost/process/v2/detail/process_handle_windows.hpp +++ b/include/boost/process/v2/detail/process_handle_windows.hpp @@ -32,6 +32,8 @@ BOOST_PROCESS_V2_DECL void terminate_if_running_(void * handle); BOOST_PROCESS_V2_DECL bool check_handle_(void* handle, error_code & ec); BOOST_PROCESS_V2_DECL bool check_pid_(pid_type pid_, error_code & ec); BOOST_PROCESS_V2_DECL void interrupt_(pid_type pid_, error_code & ec); +BOOST_PROCESS_V2_DECL void suspend_(void * handle, error_code & ec); +BOOST_PROCESS_V2_DECL void resume_(void * handle, error_code & ec); BOOST_PROCESS_V2_DECL void terminate_(void * handle, error_code & ec, native_exit_code_type & exit_code); BOOST_PROCESS_V2_DECL void request_exit_(pid_type pid_, error_code & ec); BOOST_PROCESS_V2_DECL void check_running_(void* handle, error_code & ec, native_exit_code_type & exit_status); @@ -176,6 +178,32 @@ struct basic_process_handle_win detail::throw_error(ec, "request_exit"); } + void suspend(error_code &ec) + { + detail::suspend_(handle_.native_handle(), ec); + } + + void suspend() + { + error_code ec; + suspend(ec); + if (ec) + detail::throw_error(ec, "suspend"); + } + + void resume(error_code &ec) + { + detail::resume_(handle_.native_handle(), ec); + } + + void resume() + { + error_code ec; + suspend(ec); + if (ec) + detail::throw_error(ec, "resume"); + } + void terminate(native_exit_code_type &exit_status, error_code &ec) { if (!detail::check_handle_(handle_.native_handle(), ec)) diff --git a/include/boost/process/v2/ext/cmd.hpp b/include/boost/process/v2/ext/cmd.hpp new file mode 100644 index 00000000..beca4ffd --- /dev/null +++ b/include/boost/process/v2/ext/cmd.hpp @@ -0,0 +1,55 @@ +// Copyright (c) 2022 Klemens D. Morgenstern +// Copyright (c) 2022 Samuel Venable +// +// 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_CMD_HPP +#define BOOST_PROCESS_V2_CMD_HPP + +#include +#include + +#include +#include +#include +#include + +#include + +BOOST_PROCESS_V2_BEGIN_NAMESPACE + +namespace ext { + +/// Get the argument vector from a given pid +BOOST_PROCESS_V2_DECL shell cmd(pid_type pid, error_code & ec); +BOOST_PROCESS_V2_DECL shell cmd(pid_type pid); + +#if defined(BOOST_PROCESS_V2_WINDOWS) +BOOST_PROCESS_V2_DECL shell cmd(HANDLE handle, error_code & ec); +BOOST_PROCESS_V2_DECL shell cmd(HANDLE handle); +#endif + +template +BOOST_PROCESS_V2_DECL shell cmd(basic_process_handle & handle, error_code & ec) +{ + return cmd(handle.native_handle(), ec); +} + +template +BOOST_PROCESS_V2_DECL shell cmd(basic_process_handle & handle) +{ + return cmd(handle.native_handle()); +} + +} // namespace ext + +BOOST_PROCESS_V2_END_NAMESPACE + +#if defined(BOOST_PROCESS_V2_HEADER_ONLY) + +#include + +#endif + + +#endif // BOOST_PROCESS_V2_CMD_HPP diff --git a/include/boost/process/v2/ext/cwd.hpp b/include/boost/process/v2/ext/cwd.hpp new file mode 100644 index 00000000..ec069316 --- /dev/null +++ b/include/boost/process/v2/ext/cwd.hpp @@ -0,0 +1,47 @@ +// Copyright (c) 2022 Klemens D. Morgenstern +// Copyright (c) 2022 Samuel Venable +// +// 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_CWD_HPP +#define BOOST_PROCESS_V2_CWD_HPP + +#include +#include + +#include + +BOOST_PROCESS_V2_BEGIN_NAMESPACE + +namespace ext { + +/// Obtain the current path of a process +BOOST_PROCESS_V2_DECL filesystem::path cwd(pid_type pid, error_code & ec); +BOOST_PROCESS_V2_DECL filesystem::path cwd(pid_type pid); + +#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 + +BOOST_PROCESS_V2_END_NAMESPACE + +#if defined(BOOST_PROCESS_V2_HEADER_ONLY) +#include +#endif + +#endif // BOOST_PROCESS_V2_CWD_HPP diff --git a/include/boost/process/v2/ext/detail/impl/proc_info.ipp b/include/boost/process/v2/ext/detail/impl/proc_info.ipp new file mode 100644 index 00000000..ba866735 --- /dev/null +++ b/include/boost/process/v2/ext/detail/impl/proc_info.ipp @@ -0,0 +1,127 @@ +// Copyright (c) 2022 Klemens D. Morgenstern +// Copyright (c) 2022 Samuel Venable +// +// 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_IMPL_DETAIL_PROC_INFO_IPP +#define BOOST_PROCESS_V2_IMPL_DETAIL_PROC_INFO_IPP + +#include +#include +#include +#include + +#include + +#if (defined(__APPLE__) && defined(__MACH__)) +#include +#include +#include +#include +#include +#endif + +BOOST_PROCESS_V2_BEGIN_NAMESPACE + +namespace detail +{ + +namespace ext +{ + +#if defined(BOOST_PROCESS_V2_WINDOWS) +// type of process memory to read? +enum MEMTYP {MEMCMD, MEMCWD}; +std::wstring cwd_cmd_from_proc(HANDLE proc, int type, boost::system::error_code & ec) +{ + std::wstring buffer; + PEB peb; + SIZE_T nRead = 0; + ULONG len = 0; + PROCESS_BASIC_INFORMATION pbi; + RTL_USER_PROCESS_PARAMETERS_EXTENDED upp; + + NTSTATUS status = 0; + PVOID buf = nullptr; + status = NtQueryInformationProcess(proc, ProcessBasicInformation, &pbi, sizeof(pbi), &len); + ULONG error = RtlNtStatusToDosError(status); + + if (error) + { + ec.assign(error, boost::system::system_category()); + return {}; + } + + if (!ReadProcessMemory(proc, pbi.PebBaseAddress, &peb, sizeof(peb), &nRead)) + { + ec = detail::get_last_error(); + return {}; + } + + if (!ReadProcessMemory(proc, peb.ProcessParameters, &upp, sizeof(upp), &nRead)) + { + ec = detail::get_last_error(); + return {}; + } + + if (type == MEMCWD) + { + buf = upp.CurrentDirectory.DosPath.Buffer; + len = upp.CurrentDirectory.DosPath.Length; + } + else if (type == MEMCMD) + { + buf = upp.CommandLine.Buffer; + len = upp.CommandLine.Length; + } + + buffer.resize(len / 2 + 1); + + if (!ReadProcessMemory(proc, buf, &buffer[0], len, &nRead)) + { + ec = detail::get_last_error(); + return {}; + } + + buffer.pop_back(); + return buffer; +} + +// with debug_privilege enabled allows reading info from more processes +// this includes stuff such as exe path, cwd path, cmdline, and environ +HANDLE open_process_with_debug_privilege(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + HANDLE proc = nullptr; + HANDLE hToken = nullptr; + LUID luid; + TOKEN_PRIVILEGES tkp; + if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) + { + if (LookupPrivilegeValue(nullptr, SE_DEBUG_NAME, &luid)) + { + tkp.PrivilegeCount = 1; + tkp.Privileges[0].Luid = luid; + tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + if (AdjustTokenPrivileges(hToken, false, &tkp, sizeof(tkp), nullptr, nullptr)) + { + proc = OpenProcess(PROCESS_ALL_ACCESS, false, pid); + } + } + CloseHandle(hToken); + } + if (!proc) + proc = OpenProcess(PROCESS_ALL_ACCESS, false, pid); + if (!proc) + ec = detail::get_last_error(); + return proc; +} +#endif + +} // namespace ext + +} // namespace detail + +BOOST_PROCESS_V2_END_NAMESPACE + +#endif // BOOST_PROCESS_V2_IMPL_DETAIL_PROC_INFO_IPP + diff --git a/include/boost/process/v2/ext/detail/proc_info.hpp b/include/boost/process/v2/ext/detail/proc_info.hpp new file mode 100644 index 00000000..c1c24fa3 --- /dev/null +++ b/include/boost/process/v2/ext/detail/proc_info.hpp @@ -0,0 +1,125 @@ +// Copyright (c) 2022 Klemens D. Morgenstern +// Copyright (c) 2022 Samuel Venable +// +// 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_DETAIL_PROC_INFO_HPP +#define BOOST_PROCESS_V2_DETAIL_PROC_INFO_HPP + +#include +#include +#include + +#include +#include + +#if defined(BOOST_PROCESS_V2_WINDOWS) +#include +#include +#include +#include +extern "C" ULONG NTAPI RtlNtStatusToDosError(NTSTATUS Status); +#endif + +BOOST_PROCESS_V2_BEGIN_NAMESPACE + +namespace detail +{ + +namespace ext +{ + +#if defined(BOOST_PROCESS_V2_WINDOWS) +#if !defined(_MSC_VER) +#pragma pack(push, 8) +#else +#include +#endif + +/* CURDIR struct from: + https://github.com/processhacker/phnt/ + CC BY 4.0 licence */ + +typedef struct { + UNICODE_STRING DosPath; + HANDLE Handle; +} CURDIR; + +/* RTL_DRIVE_LETTER_CURDIR struct from: + https://github.com/processhacker/phnt/ + CC BY 4.0 licence */ + +typedef struct { + USHORT Flags; + USHORT Length; + ULONG TimeStamp; + STRING DosPath; +} RTL_DRIVE_LETTER_CURDIR; + +/* RTL_USER_PROCESS_PARAMETERS struct from: + https://github.com/processhacker/phnt/ + CC BY 4.0 licence */ + +typedef struct { + ULONG MaximumLength; + ULONG Length; + ULONG Flags; + ULONG DebugFlags; + HANDLE ConsoleHandle; + ULONG ConsoleFlags; + HANDLE StandardInput; + HANDLE StandardOutput; + HANDLE StandardError; + CURDIR CurrentDirectory; + UNICODE_STRING DllPath; + UNICODE_STRING ImagePathName; + UNICODE_STRING CommandLine; + PVOID Environment; + ULONG StartingX; + ULONG StartingY; + ULONG CountX; + ULONG CountY; + ULONG CountCharsX; + ULONG CountCharsY; + ULONG FillAttribute; + ULONG WindowFlags; + ULONG ShowWindowFlags; + UNICODE_STRING WindowTitle; + UNICODE_STRING DesktopInfo; + UNICODE_STRING ShellInfo; + UNICODE_STRING RuntimeData; + RTL_DRIVE_LETTER_CURDIR CurrentDirectories[32]; + ULONG_PTR EnvironmentSize; + ULONG_PTR EnvironmentVersion; + PVOID PackageDependencyData; + ULONG ProcessGroupId; + ULONG LoaderThreads; + UNICODE_STRING RedirectionDllName; + UNICODE_STRING HeapPartitionName; + ULONG_PTR DefaultThreadpoolCpuSetMasks; + ULONG DefaultThreadpoolCpuSetMaskCount; +} RTL_USER_PROCESS_PARAMETERS_EXTENDED; + +#if !defined(_MSC_VER) +#pragma pack(pop) +#else +#include +#endif +BOOST_PROCESS_V2_DECL std::wstring cwd_cmd_from_proc(HANDLE proc, int type, boost::system::error_code & ec); +BOOST_PROCESS_V2_DECL HANDLE open_process_with_debug_privilege(boost::process::v2::pid_type pid, boost::system::error_code & ec); +#endif + +} // namespace ext + +} // namespace detail + +BOOST_PROCESS_V2_END_NAMESPACE + +#if defined(BOOST_PROCESS_V2_HEADER_ONLY) + +#include + +#endif + +#endif // BOOST_PROCESS_V2_DETAIL_PROC_INFO_HPP + diff --git a/include/boost/process/v2/ext/env.hpp b/include/boost/process/v2/ext/env.hpp new file mode 100644 index 00000000..daf2eac8 --- /dev/null +++ b/include/boost/process/v2/ext/env.hpp @@ -0,0 +1,138 @@ +// Copyright (c) 2022 Klemens D. Morgenstern +// Copyright (c) 2022 Samuel Venable +// +// 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_ENV_HPP +#define BOOST_PROCESS_V2_ENV_HPP +#include +#include + +#include +#include +#include +#include + +#include + +BOOST_PROCESS_V2_BEGIN_NAMESPACE + +namespace detail +{ +namespace ext +{ + +#if defined(BOOST_PROCESS_V2_WINDOWS) +using native_env_handle_type = wchar_t *; +using native_env_iterator = wchar_t *; +#else +using native_env_handle_type = char *; +using native_env_iterator = char *; +#endif + +struct native_env_handle_deleter +{ + BOOST_PROCESS_V2_DECL void operator()(native_env_handle_type) const; +}; + +BOOST_PROCESS_V2_DECL native_env_iterator next(native_env_iterator nh); +BOOST_PROCESS_V2_DECL native_env_iterator find_end(native_env_iterator nh); +BOOST_PROCESS_V2_DECL const environment::char_type * dereference(native_env_iterator iterator); + +} // namespace ext +} // namespace detail + +namespace ext { + +struct env_view +{ + using native_handle_type = detail::ext::native_env_handle_type; + using value_type = environment::key_value_pair_view; + + env_view() = default; + env_view(env_view && nt) = default; + + native_handle_type native_handle() { return handle_.get(); } + + + struct iterator + { + using value_type = environment::key_value_pair_view; + using difference_type = int; + using reference = environment::key_value_pair_view; + using pointer = environment::key_value_pair_view; + using iterator_category = std::forward_iterator_tag; + + iterator() = default; + iterator(const iterator & ) = default; + iterator(const detail::ext::native_env_iterator &native_handle) : iterator_(native_handle) {} + + iterator & operator++() + { + iterator_ = detail::ext::next(iterator_); + return *this; + } + + iterator operator++(int) + { + auto last = *this; + iterator_ = detail::ext::next(iterator_); + return last; + } + environment::key_value_pair_view operator*() const + { + return detail::ext::dereference(iterator_); + } + + friend bool operator==(const iterator & l, const iterator & r) {return l.iterator_ == r.iterator_;} + friend bool operator!=(const iterator & l, const iterator & r) {return l.iterator_ != r.iterator_;} + + private: + detail::ext::native_env_iterator iterator_; + }; + + iterator begin() const {return iterator(handle_.get());} + iterator end() const {return iterator(detail::ext::find_end(handle_.get()));} + + private: + friend BOOST_PROCESS_V2_DECL env_view env(pid_type pid, error_code & ec); + #if defined(BOOST_PROCESS_V2_WINDOWS) + friend BOOST_PROCESS_V2_DECL env_view env(HANDLE handle, error_code & ec); + #endif + + std::unique_ptr::type, + detail::ext::native_env_handle_deleter> handle_; +}; + +/// Get the argument vector from a given pid +BOOST_PROCESS_V2_DECL env_view env(pid_type pid, error_code & ec); +BOOST_PROCESS_V2_DECL env_view env(pid_type pid); + +#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 + +BOOST_PROCESS_V2_END_NAMESPACE + +#if defined(BOOST_PROCESS_V2_HEADER_ONLY) + +#include + +#endif +#endif // BOOST_PROCESS_V2_ENV_HPP diff --git a/include/boost/process/v2/ext/exe.hpp b/include/boost/process/v2/ext/exe.hpp new file mode 100644 index 00000000..8b48ddfd --- /dev/null +++ b/include/boost/process/v2/ext/exe.hpp @@ -0,0 +1,49 @@ +// Copyright (c) 2022 Klemens D. Morgenstern +// Copyright (c) 2022 Samuel Venable +// +// 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_EXE_HPP +#define BOOST_PROCESS_V2_EXE_HPP + +#include +#include + +#include +#include + +BOOST_PROCESS_V2_BEGIN_NAMESPACE + +namespace ext { + +/// Return the executable path from pid +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) +{ + return exe(handle.native_handle(), ec); +} + +template +filesystem::path exe(basic_process_handle & handle) +{ + return exe(handle.native_handle()); +} + +} // namespace ext + +BOOST_PROCESS_V2_END_NAMESPACE + +#if defined(BOOST_PROCESS_V2_HEADER_ONLY) +#include +#endif + +#endif // BOOST_PROCESS_V2_EXE_HPP + diff --git a/include/boost/process/v2/ext/impl/cmd.ipp b/include/boost/process/v2/ext/impl/cmd.ipp new file mode 100644 index 00000000..466a4151 --- /dev/null +++ b/include/boost/process/v2/ext/impl/cmd.ipp @@ -0,0 +1,468 @@ +// Copyright (c) 2022 Klemens D. Morgenstern +// Copyright (c) 2022 Samuel Venable +// +// 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_IMPL_CMD_IPP +#define BOOST_PROCESS_V2_IMPL_CMD_IPP + +#include +#include +#include +#include +#include + +#if defined(BOOST_PROCESS_V2_WINDOWS) +#include +#include +#else +#include +#endif + +#if (defined(__linux__) || defined(__ANDROID__)) +#include +#endif + +#if defined(__FreeBSD__) +#include +#include +#include +#include +#include +#include +#endif + +#if (defined(__DragonFly__) || defined(__OpenBSD__)) +#include +#include +#include +#include +#include +#endif + +#if defined(__NetBSD__) +#include +#include +#include +#include +#endif + +#if defined(__sun) +#include +#include +#include +#include +#include +#endif + +BOOST_PROCESS_V2_BEGIN_NAMESPACE + +struct make_cmd_shell_ +{ +#if defined(BOOST_PROCESS_V2_WINDOWS) + static shell make(std::wstring data) + { + shell res; + res.input_ = res.buffer_ = std::move(data); + res.parse_(); + return res; + } +#else + static shell make(std::string data, + int argc, char ** argv, + void(*free_func)(int, char**)) + { + shell res; + res.argc_ = argc; + res.input_ = res.buffer_ = std::move(data); + res.argv_ = argv; + res.free_argv_ = free_func; + + return res; + } + + static shell clone(char ** cmd) + { + shell res; + res.argc_ = 0; + std::size_t str_lengths = 0; + for (auto c = cmd; *c != nullptr; c++) + { + res.argc_++; + 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]; + + for (int i = 0; i < res.argc_; i++) + { + const auto ln = std::strlen(cmd[i]); + res.argv_[i] = std::strcpy(p, cmd[i]); + p += (ln + 1); + } + + return res; + } + +#endif +}; + +namespace ext { + +#if defined(BOOST_PROCESS_V2_WINDOWS) + +shell cmd(HANDLE proc, error_code & ec) +{ + std::wstring buffer = boost::process::v2::detail::ext::cwd_cmd_from_proc(proc, 0/*=MEMCMD*/, ec); + + if (!ec) + return make_cmd_shell_::make(std::move(buffer)); + else + return {}; +} + +shell cmd(HANDLE proc) +{ + boost::system::error_code ec; + auto res = cmd(proc, ec); + if (ec) + detail::throw_error(ec, "cmd"); + return res; +} + +shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + struct del + { + void operator()(HANDLE h) + { + ::CloseHandle(h); + }; + }; + std::unique_ptr proc{detail::ext::open_process_with_debug_privilege(pid, ec)}; + if (proc == nullptr) + ec = detail::get_last_error(); + else + return cmd(proc.get(), ec); + +} + +#elif (defined(__APPLE__) && defined(__MACH__)) + +shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + int mib[3] = {CTL_KERN, KERN_ARGMAX, 0}; + int argmax = 0; + auto size = sizeof(argmax); + if (sysctl(mib, 2, &argmax, &size, nullptr, 0) == -1) + { + ec = detail::get_last_error(); + return {}; + } + + std::string procargs; + procargs.resize(argmax - 1); + mib[1] = KERN_PROCARGS; + mib[2] = pid; + + size = argmax; + + if (sysctl(mib, 3, &*procargs.begin(), &size, nullptr, 0) != 0) + { + ec = detail::get_last_error(); + return {}; + } + + int argc = *reinterpret_cast(procargs.data()); + auto itr = procargs.begin() + sizeof(argc); + + std::unique_ptr argv{new char*[argc + 1]}; + const auto end = procargs.end(); + + argv[argc] = nullptr; //args is a null-terminated list + + for (auto n = 0u; n <= argc; n++) + { + auto e = std::find(itr, end, '\0'); + if (e == end && n < argc) // something off + { + ec.assign(EINVAL, system_category()); + return {}; + } + argv[n] = &*itr; + itr = e + 1; // start searching start + } + + auto fr_func = +[](int argc, char ** argv) {delete [] argv;}; + + return make_cmd_shell_::make(std::move(procargs), argc, argv.release(), fr_func); +} + +#elif (defined(__linux__) || defined(__ANDROID__)) + +shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + std::string procargs; + procargs.resize(4096); + int f = ::open(("/proc/" + std::to_string(pid) + "/cmdline").c_str(), O_RDONLY); + + while (procargs.back() != EOF) + { + auto r = ::read(f, &*(procargs.end() - 4096), 4096); + if (r < 0) + { + ec = detail::get_last_error(); + ::close(f); + return {}; + } + if (r < 4096) // done! + { + procargs.resize(procargs.size() - 4096 + r); + break; + } + procargs.resize(procargs.size() + 4096); + } + ::close(f); + + if (procargs.back() == EOF) + procargs.pop_back(); + + auto argc = std::count(procargs.begin(), procargs.end(), '\0'); + + auto itr = procargs.begin(); + + std::unique_ptr argv{new char*[argc + 1]}; + const auto end = procargs.end(); + + argv[argc] = nullptr; //args is a null-terminated list + + + for (auto n = 0u; n <= argc; n++) + { + auto e = std::find(itr, end, '\0'); + if (e == end && n < argc) // something off + { + ec.assign(EINVAL, system_category()); + return {}; + } + argv[n] = &*itr; + itr = e + 1; // start searching start + } + + auto fr_func = +[](int argc, char ** argv) {delete [] argv;}; + + return make_cmd_shell_::make(std::move(procargs), argc, argv.release(), fr_func); +} + +#elif defined(__FreeBSD__) + +shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + struct cl_proc_stat + { + void operator()(struct procstat *proc_stat) + { + procstat_close(proc_stat); + } + }; + std::unique_ptr proc_stat{procstat_open_sysctl()}; + if (!proc_stat) + { + ec = detail::get_last_error(); + return {}; + } + + struct proc_info_close + { + struct procstat * proc_stat; + + void operator()(struct kinfo_proc * proc_info) + { + procstat_freeprocs(proc_stat, proc_info); + } + }; + + unsigned cntp; + std::unique_ptr proc_info{ + procstat_getprocs(proc_stat.get(), KERN_PROC_PID, pid, &cntp), + proc_info_close{proc_stat.get()}}; + + if (!proc_info) + { + ec = detail::get_last_error(); + return {}; + } + + char **cmd = procstat_getargv(proc_stat.get(), proc_info.get(), 0); + if (!cmd) + { + 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); +} + +#elif defined(__DragonFly__) + +shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + int cntp = 0; + kinfo_proc *proc_info = nullptr; + const char *nlistf, *memf; + nlistf = memf = "/dev/null"; + struct closer + { + void operator()(kvm_t * kd) + { + kvm_close(kd); + } + }; + + std::unique_ptr kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)}; + if (!kd) {ec = detail::get_last_error(); return {};} + if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_PID, pid, &cntp))) + { + char **cmd = kvm_getargv(kd.get(), proc_info, 0); + if (cmd) + return make_cmd_shell_::clone(cmd); + else + ec = detail::get_last_error(); + } + else + ec = detail::get_last_error(); + return {}; +} + +#elif defined(__NetBSD__) + +shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + + std::vector vec; + int cntp = 0; + kinfo_proc2 *proc_info = nullptr; + struct closer + { + void operator()(kvm_t * kd) + { + kvm_close(kd); + } + }; + + std::unique_ptr kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)}; + + if (!kd) {ec = detail::get_last_error(); return vec;} + if ((proc_info = kvm_getproc2(kd.get(), KERN_PROC_PID, pid, sizeof(struct kinfo_proc2), &cntp))) + { + char **cmd = kvm_getargv2(kd.get(), proc_info, 0); + if (cmd) + return make_cmd_shell_::clone(cmd); + else + ec = detail::get_last_error(); + } + else + ec = detail::get_last_error(); + return vec; +} + +#elif defined(__OpenBSD__) + +shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + std::vector vec; + int cntp = 0; + kinfo_proc *proc_info = nullptr; + + struct closer + { + void operator()(kvm_t * kd) + { + kvm_close(kd); + } + }; + + std::unique_ptr kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)}; + if (!kd) {ec = detail::get_last_error(); return vec;} + if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &cntp))) + { + char **cmd = kvm_getargv(kd.get(), proc_info, 0); + if (cmd) + return make_cmd_shell_::clone(cmd); + else + ec = detail::get_last_error(); + } + else + ec = detail::get_last_error(); + kvm_close(kd); + return {}; +} + +#elif defined(__sun) + +shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + char **cmd = nullptr; + proc *proc_info = nullptr; + user *proc_user = nullptr; + kd = kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr); + if (!kd) {ec = detail::get_last_error(); return {};} + if ((proc_info = kvm_getproc(kd, pid))) + { + if ((proc_user = kvm_getu(kd, proc_info))) + { + if (!kvm_getcmd(kd, proc_info, proc_user, &cmd, nullptr)) + { + int argc = 0; + for (int i = 0; cmd[i] != nullptr; i++) + argc ++; + return make_cmd_shell_::make( + {}, argc, cmd, + +[](int, char ** argv) {::free(argv);}) + } + else + ec = detail::get_last_error(); + } + else + ec = detail::get_last_error(); + } + else + ec = detail::get_last_error(); + + kvm_close(kd); + return {}; +} + +#else +#error "Platform not supported" +#endif + +shell cmd(boost::process::v2::pid_type pid) +{ + boost::system::error_code ec; + auto res = cmd(pid, ec); + if (ec) + detail::throw_error(ec, "cmd"); + return res; +} + +} // namespace ext + +BOOST_PROCESS_V2_END_NAMESPACE + +#endif // BOOST_PROCESS_V2_IMPL_CMD_IPP + diff --git a/include/boost/process/v2/ext/impl/cwd.ipp b/include/boost/process/v2/ext/impl/cwd.ipp new file mode 100644 index 00000000..a4a4e45b --- /dev/null +++ b/include/boost/process/v2/ext/impl/cwd.ipp @@ -0,0 +1,234 @@ +// Copyright (c) 2022 Klemens D. Morgenstern +// Copyright (c) 2022 Samuel Venable +// +// 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_IMPL_CWD_IPP +#define BOOST_PROCESS_V2_IMPL_CWD_IPP + +#include +#include +#include +#include +#include + +#include + +#if defined(BOOST_PROCESS_V2_WINDOWS) +#include +#else +#include +#endif + +#if (defined(__APPLE__) && defined(__MACH__)) +#include +#include +#endif + +#if (defined(BOOST_PROCESS_V2_WINDOWS) || defined(__linux__) || defined(__ANDROID__) || defined(__sun)) +#include +#endif + +#if defined(__FreeBSD__) +#include +#include +#include +#include +#include +#include +#endif + +#if (defined(__NetBSD__) || defined(__OpenBSD__)) +#include +#include +#endif + +#if defined(__DragonFly__) +#include +#include +#endif + +#ifdef BOOST_PROCESS_USE_STD_FS +namespace filesystem = std::filesystem; +#else +namespace filesystem = boost::filesystem; +#endif + +BOOST_PROCESS_V2_BEGIN_NAMESPACE + +namespace ext { + +#if defined(BOOST_PROCESS_V2_WINDOWS) + +filesystem::path cwd(HANDLE proc, boost::system::error_code & ec) +{ + auto buffer = boost::process::v2::detail::ext::cwd_cmd_from_proc(proc, 1/*=MEMCWD*/, ec); + if (!buffer.empty()) + return filesystem::canonical(buffer, ec); + else + ec = detail::get_last_error(); + return ""; +} + +filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + struct del + { + void operator()(HANDLE h) + { + ::CloseHandle(h); + }; + }; + std::unique_ptr proc{detail::ext::open_process_with_debug_privilege(pid, ec)}; + if (proc == nullptr) + ec = detail::get_last_error(); + else + return cwd(proc.get(), ec); + return {}; +} + +filesystem::path cwd(HANDLE proc) +{ + boost::system::error_code ec; + auto res = cwd(proc, ec); + if (ec) + detail::throw_error(ec, "cwd"); + return res; +} + +#elif (defined(__APPLE__) && defined(__MACH__)) + +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) { + return filesystem::canonical(vpi.pvi_cdir.vip_path, ec); + } + ec = detail::get_last_error(); + return ""; +} + +#elif (defined(__linux__) || defined(__ANDROID__) || defined(__sun)) + +filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + return filesystem::canonical( + filesystem::path("/proc") / std::to_string(pid) / "cwd", ec); +} + +#elif defined(__FreeBSD__) + +// FIXME: Add error handling. +filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + filesystem::path path; + unsigned cntp = 0; + procstat *proc_stat = procstat_open_sysctl(); + if (proc_stat) { + kinfo_proc *proc_info = procstat_getprocs(proc_stat, KERN_PROC_PID, pid, &cntp); + if (proc_info) { + filestat_list *head = procstat_getfiles(proc_stat, proc_info, 0); + if (head) { + filestat *fst = nullptr; + STAILQ_FOREACH(fst, head, next) { + if (fst->fs_uflags & PS_FST_UFLAG_CDIR) + { + path = filesystem::canonical(fst->fs_path, ec); + } + } + procstat_freefiles(proc_stat, head); + } + 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 path; +} + +#elif defined(__DragonFly__) + +// FIXME: Add error handling. +filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + filesystem::path path; + /* Probably the hackiest thing ever we are doing here, because the "official" API is broken OS-level. */ + FILE *fp = popen(("pos=`ans=\\`/usr/bin/fstat -w -p " + std::to_string(pid) + " | /usr/bin/sed -n 1p\\`; " + + "/usr/bin/awk -v ans=\"$ans\" 'BEGIN{print index(ans, \"INUM\")}'`; str=`/usr/bin/fstat -w -p " + + std::to_string(pid) + " | /usr/bin/sed -n 3p`; /usr/bin/awk -v str=\"$str\" -v pos=\"$pos\" " + + "'BEGIN{print substr(str, 0, pos + 4)}' | /usr/bin/awk 'NF{NF--};1 {$1=$2=$3=$4=\"\"; print" + + " substr($0, 5)'}").c_str(), "r"); + if (fp) + { + char buffer[PATH_MAX]; + if (fgets(buffer, sizeof(buffer), fp)) + { + std::string str = buffer; + std::size_t pos = str.find("\n", strlen(buffer) - 1); + if (pos != std::string::npos) + { + str.replace(pos, 1, ""); + } + path = filesystem::canonical(str.c_str(), ec); + } + else + ec = detail::get_last_error(); + pclose(fp); + } + else + ec = detail::get_last_error(); + return path; +} + +#elif (defined(__NetBSD__) || defined(__OpenBSD__)) + +filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + std::string path; +#if defined(__NetBSD__) + int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_CWD}; + const std::size_t sz = 4; +#elif defined(__OpenBSD__) + int mib[3] = {CTL_KERN, KERN_PROC_CWD, pid}; + const std::size_t sz = 3; +#endif + std::size_t len = 0; + if (sysctl(mib, sz, nullptr, &len, nullptr, 0) == 0) + { + std::string strbuff; + strbuff.resize(len); + if (sysctl(mib, 4, &strbuff[0], &len, nullptr, 0) == 0) + { + filesystem::canonical(strbuff, ec); + } + else + ec = detail::get_last_error(); + } + + return ""; +} + +#else +#error "Platform not supported" +#endif + +filesystem::path cwd(boost::process::v2::pid_type pid) +{ + boost::system::error_code ec; + auto res = cwd(pid, ec); + if (ec) + detail::throw_error(ec, "cwd"); + return res; +} + +} // namespace ext + +BOOST_PROCESS_V2_END_NAMESPACE + +#endif // BOOST_PROCESS_V2_IMPL_CWD_IPP + diff --git a/include/boost/process/v2/ext/impl/env.ipp b/include/boost/process/v2/ext/impl/env.ipp new file mode 100644 index 00000000..7143d907 --- /dev/null +++ b/include/boost/process/v2/ext/impl/env.ipp @@ -0,0 +1,295 @@ +// Copyright (c) 2022 Klemens D. Morgenstern +// +// 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_IMPL_ENV_IPP +#define BOOST_PROCESS_V2_EXT_IMPL_ENV_IPP + +#include +#include +#include +#include +#include + +#if defined(BOOST_PROCESS_V2_WINDOWS) +#include +#else +#include +#endif + +#if (defined(__linux__) || defined(__ANDROID__)) +#include +#endif + +BOOST_PROCESS_V2_BEGIN_NAMESPACE + +namespace detail { +namespace ext { + +#if defined(BOOST_PROCESS_V2_WINDOWS) + +void native_env_handle_deleter::operator()(native_env_handle_type h) const +{ + delete [] h; +} + +native_env_iterator next(native_env_iterator nh) +{ + while (*nh != L'\0') + nh ++; + return ++nh ; +} +native_env_iterator find_end(native_env_iterator nh) +{ + while (*nh - 1 != L'\0' && *nh != L'\0') + nh ++; + return nh ; +} + +const environment::char_type * dereference(native_env_iterator iterator) +{ + return iterator; +} + +#elif (defined(__linux__) || defined(__ANDROID__)) +//linux stores this as a blob with an EOF at the end + +void native_env_handle_deleter::operator()(native_env_handle_type h) const +{ + delete [] h; +} + +native_env_iterator next(native_env_iterator nh) +{ + while (*nh != '\0') + nh ++; + return ++nh ; +} +native_env_iterator find_end(native_env_iterator nh) +{ + while (*nh != EOF) + nh ++; + return nh ; +} + +const environment::char_type * dereference(native_env_iterator iterator) +{ + return iterator; +} + +#else + +void native_env_handle_deleter::operator()(native_env_handle_type h) const +{ + delete [] h; +} + +native_env_iterator next(native_env_iterator nh) +{ + while (*nh != '\0') + nh ++; + return ++nh ; +} +native_env_iterator find_end(native_env_iterator nh) +{ + while (*nh - 1 != '\0' && *nh != '\0') + nh ++; + return nh ; +} + +#endif + +} +} + +namespace ext +{ + +#if defined(BOOST_PROCESS_V2_WINDOWS) + +env_view env(HANDLE proc, boost::system::error_code & ec) +{ + wchar_t *buffer = nullptr; + PEB peb; + SIZE_T nRead = 0; + ULONG len = 0; + PROCESS_BASIC_INFORMATION pbi; + detail::ext::RTL_USER_PROCESS_PARAMETERS_EXTENDED upp; + + NTSTATUS status = 0; + PVOID buf = nullptr; + status = NtQueryInformationProcess(proc, ProcessBasicInformation, &pbi, sizeof(pbi), &len); + ULONG error = RtlNtStatusToDosError(status); + + if (error) + { + ec.assign(error, boost::system::system_category()); + return {}; + } + + if (!ReadProcessMemory(proc, pbi.PebBaseAddress, &peb, sizeof(peb), &nRead)) + { + ec = detail::get_last_error(); + return {}; + } + + if (!ReadProcessMemory(proc, peb.ProcessParameters, &upp, sizeof(upp), &nRead)) + { + ec = detail::get_last_error(); + return {}; + } + + env_view ev; + buf = upp.Environment; + len = (ULONG)upp.EnvironmentSize; + ev.handle_.reset(new wchar_t[len / 2 + 1]()); + + if (!ReadProcessMemory(proc, buf, ev.handle_.get(), len, &nRead)) + { + ec = detail::get_last_error(); + return {}; + } + + ev.handle_.get()[len / 2] = L'\0'; + return ev; +} + +env_view env(HANDLE handle) +{ + boost::system::error_code ec; + auto res = env(handle, ec); + if (ec) + detail::throw_error(ec, "env"); + return res; +} + +env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + struct del + { + void operator()(HANDLE h) + { + ::CloseHandle(h); + }; + }; + std::unique_ptr proc{detail::ext::open_process_with_debug_privilege(pid, ec)}; + if (proc == nullptr) + ec = detail::get_last_error(); + else + return env(proc.get(), ec); + + return {}; +} + +#elif (defined(__APPLE___) || defined(__MACH__)) + +env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + int mib[3] = {CTL_KERN, KERN_ARGMAX, 0}; + int argmax = 0; + auto size = sizeof(argmax); + if (sysctl(mib, 2, &argmax, &size, nullptr, 0) == -1) + { + ec = detail::get_last_error(); + return {}; + } + + std::string procargs; + procargs.resize(argmax - 1); + mib[1] = KERN_PROCARGS2; + mib[2] = pid; + + size = argmax; + + if (sysctl(mib, 3, &*procargs.begin(), &size, nullptr, 0) != 0) + { + ec = detail::get_last_error(); + return {}; + } + + memcpy(&nargs, &*procargs.begin(), sizeof(nargs)); + char *cp = &*procargs.begin() + sizeof(nargs); + + for (; cp < &&*procargs.begin()[size]; cp++) { + if (*cp == '\0') break; + } + + if (cp == &procargs[s]) { + return {}; + } + + for (; cp < &&*procargs.begin()[size]; cp++) { + if (*cp != '\0') break; + } + + if (cp == &&*procargs.begin()[size]) { + return {}; + } + + int i = 0; + char *sp = cp; + std::vector vec; + + while ((*sp != '\0' || i < nargs) && sp < &&*procargs.begin()[size]) { + if (i >= nargs) { + vec.push_back(*sp); + } + sp += 1; + } + + env_view ev; + ev.handle_.reset(new char[vec.size()]()); + std::copy(vec.begin(), vec.end(), ev.handle_.get()); + return ev; +} + +#elif (defined(__linux__) || defined(__ANDROID__)) + +env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + std::size_t size = 0; + std::unique_ptr procargs{}; + + int f = ::open(("/proc/" + std::to_string(pid) + "/environ").c_str(), O_RDONLY); + + while (!procargs || procargs.get()[size - 1] != EOF) + { + std::unique_ptr buf{new char[size + 4096]}; + if (size > 0) + std::memmove(buf.get(), procargs.get(), size); + auto r = ::read(f, buf.get() + size, 4096); + if (r < 0) + { + ec = detail::get_last_error(); + ::close(f); + return {}; + } + procargs = std::move(buf); + size += r; + if (r < 4096) // done! + { + procargs.get()[size] = EOF; + break; + } + } + ::close(f); + + env_view ev; + ev.handle_ = std::move(procargs); + return ev; +} + +#endif + +env_view env(boost::process::v2::pid_type pid) +{ + boost::system::error_code ec; + auto res = env(pid, ec); + if (ec) + detail::throw_error(ec, "env"); + return res; +} +} +BOOST_PROCESS_V2_END_NAMESPACE + +#endif //BOOST_PROCESS_V2_EXT_IMPL_ENV_IPP diff --git a/include/boost/process/v2/ext/impl/exe.ipp b/include/boost/process/v2/ext/impl/exe.ipp new file mode 100644 index 00000000..fa772821 --- /dev/null +++ b/include/boost/process/v2/ext/impl/exe.ipp @@ -0,0 +1,192 @@ +// Copyright (c) 2022 Klemens D. Morgenstern +// Copyright (c) 2022 Samuel Venable +// +// 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_IMPL_EXE_IPP +#define BOOST_PROCESS_V2_IMPL_EXE_IPP + +#include +#include +#include +#include +#include + +#include +#include + +#if defined(BOOST_PROCESS_V2_WINDOWS) +#include +#else +#include +#endif + +#if (defined(__APPLE__) && defined(__MACH__)) +#include +#include +#endif + +#if (defined(BOOST_PROCESS_V2_WINDOWS) || defined(__linux__) || defined(__ANDROID__) || defined(__sun)) +#include +#endif + +#if (defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__)) +#include +#include +#if !defined(__FreeBSD__) +#include +#endif +#endif + +#if defined(__OpenBSD__) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +BOOST_PROCESS_V2_BEGIN_NAMESPACE + +namespace ext { + +#if defined(BOOST_PROCESS_V2_WINDOWS) + +filesystem::path exe(HANDLE process_handle) +{ + boost::system::error_code ec; + auto res = exe(process_handle, ec); + if (ec) + detail::throw_error(ec, "exe"); + return res; +} + + +filesystem::path exe(HANDLE proc, boost::system::error_code & ec) +{ + wchar_t buffer[MAX_PATH]; + // On input, specifies the size of the lpExeName buffer, in characters. + DWORD size = MAX_PATH; + if (QueryFullProcessImageNameW(proc, 0, buffer, &size)) + { + return filesystem::canonical(buffer, ec); + } + else + ec = detail::get_last_error(); + + return ""; +} + +filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + if (pid == GetCurrentProcessId()) + { + wchar_t buffer[MAX_PATH]; + if (GetModuleFileNameW(nullptr, buffer, sizeof(buffer))) + { + return filesystem::canonical(buffer, ec); + } + } + else + { + struct del + { + void operator()(HANDLE h) + { + ::CloseHandle(h); + }; + }; + std::unique_ptr proc{detail::ext::open_process_with_debug_privilege(pid, ec)}; + if (proc == nullptr) + ec = detail::get_last_error(); + else + return exe(proc.get(), ec); + } + return ""; +} + +#elif (defined(__APPLE__) && defined(__MACH__)) + +filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + char buffer[PROC_PIDPATHINFO_MAXSIZE]; + if (proc_pidpath(pid, buffer, sizeof(buffer)) > 0) + { + return filesystem::canonical(buffer, ec); + } + ec = detail::get_last_error(); + return ""; +} + +#elif (defined(__linux__) || defined(__ANDROID__) || defined(__sun)) + +filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ +#if (defined(__linux__) || defined(__ANDROID__)) + return filesystem::canonical( + filesystem::path("/proc") / std::to_string(pid) / "exe", ec + ); +#elif defined(__sun) + return fileystem::canonical( + filesystem::path("/proc") / std::to_string(pid) / "path/a.out" + ); +#endif +} + +#elif (defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__)) + +filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ +#if (defined(__FreeBSD__) || defined(__DragonFly__)) + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, pid}; +#elif defined(__NetBSD__) + int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_PATHNAME}; +#endif + std::size_t len = 0; + if (sysctl(mib, 4, nullptr, &len, nullptr, 0) == 0) + { + std::string strbuff; + strbuff.resize(len); + if (sysctl(mib, 4, &strbuff[0], &len, nullptr, 0) == 0) + { + return filesystem::canonical(strbuff, ec); + } + } + + ec = detail::get_last_error(); + return ""; +} + +#elif defined(__OpenBSD__) + +filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code & ec) +{ + ec.assign(ENOTSUP, boost::system::system_category()); + return ""; +} + +#else +#error "Platform not supported" +#endif + +filesystem::path exe(boost::process::v2::pid_type pid) +{ + boost::system::error_code ec; + auto res = exe(pid, ec); + if (ec) + detail::throw_error(ec, "exe"); + return res; +} + + +} // namespace ext + +BOOST_PROCESS_V2_END_NAMESPACE + +#endif // BOOST_PROCESS_V2_IMPL_EXE_IPP + diff --git a/include/boost/process/v2/impl/pid.ipp b/include/boost/process/v2/impl/pid.ipp index 1ac40acb..37dae095 100644 --- a/include/boost/process/v2/impl/pid.ipp +++ b/include/boost/process/v2/impl/pid.ipp @@ -1,4 +1,5 @@ // Copyright (c) 2022 Klemens D. Morgenstern +// Copyright (c) 2022 Samuel Venable // // 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) @@ -6,14 +7,56 @@ #define BOOST_PROCESS_V2_IMPL_PID_IPP #include +#include +#include #include #if defined(BOOST_PROCESS_V2_WINDOWS) #include +#include #else #include #endif +#if (defined(__APPLE__) && defined(__MACH__)) +#include +#include +#endif + +#if (defined(__linux__) || defined(__ANDROID__)) +#include +#endif + +#if defined(__FreeBSD__) +#include +#include +#include +#include +#endif + +#if (defined(__DragonFly__) || defined(__OpenBSD__)) +#include +#include +#include +#include +#include +#endif + +#if defined(__NetBSD__) +#include +#include +#include +#include +#endif + +#if defined(__sun) +#include +#include +#include +#include +#include +#endif + BOOST_PROCESS_V2_BEGIN_NAMESPACE #if defined(BOOST_PROCESS_V2_WINDOWS) @@ -22,6 +65,700 @@ pid_type current_pid() {return ::GetCurrentProcessId();} pid_type current_pid() {return ::getpid();} #endif +#if defined(BOOST_PROCESS_V2_WINDOWS) + +std::vector all_pids(boost::system::error_code & ec) +{ + std::vector vec; + HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (!hp) + { + ec = detail::get_last_error(); + return vec; + } + PROCESSENTRY32 pe; + pe.dwSize = sizeof(PROCESSENTRY32); + if (Process32First(hp, &pe)) + { + do + { + vec.push_back(pe.th32ProcessID); + } while (Process32Next(hp, &pe)); + } + CloseHandle(hp); + return vec; +} + +pid_type parent_pid(pid_type pid, boost::system::error_code & ec) +{ + pid_type ppid = static_cast(-1); + HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (!hp) + { + ec = detail::get_last_error(); + return ppid; + } + PROCESSENTRY32 pe; + pe.dwSize = sizeof(PROCESSENTRY32); + if (Process32First(hp, &pe)) + { + do + { + if (pe.th32ProcessID == pid) + { + ppid = pe.th32ParentProcessID; + break; + } + } + while (Process32Next(hp, &pe)); + } + CloseHandle(hp); + return ppid; +} + +std::vector child_pids(pid_type pid, boost::system::error_code & ec) +{ + std::vector vec; + HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (!hp) + { + ec = detail::get_last_error(); + return vec; + } + PROCESSENTRY32 pe; + pe.dwSize = sizeof(PROCESSENTRY32); + if (Process32First(hp, &pe)) + { + do + { + if (pe.th32ParentProcessID == pid) + { + vec.push_back(pe.th32ProcessID); + } + } + while (Process32Next(hp, &pe)); + } + CloseHandle(hp); + return vec; +} + +#elif (defined(__APPLE__) && defined(__MACH__)) + +std::vector all_pids(boost::system::error_code & ec) +{ + std::vector vec; + vec.reserve(proc_listpids(PROC_ALL_PIDS, 0, nullptr, 0)); + if (proc_listpids(PROC_ALL_PIDS, 0, &vec[0], sizeof(pid_type) * vec.size())) + { + ec = detail::get_last_error(); + return {}; + } + auto itr = std::partition(vec.begin(), vec.end(), [](pid_type pt) {return pt != 0;}); + vec.erase(itr, vec.end()); + std::reverse(vec.begin(), vec.end()); + return vec; +} + +pid_type parent_pid(pid_type pid, boost::system::error_code & ec) +{ + pid_type ppid = static_cast(-1); + proc_bsdinfo proc_info; + if (proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &proc_info, sizeof(proc_info)) <= 0) + { + ec = detail::get_last_error(); + return ppid; + } + else + ppid = proc_info.pbi_ppid; + return ppid; +} + +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)) + { + ec = detail::get_last_error(); + return {}; + } + auto itr = std::partition(vec.begin(), vec.end(), [](pid_type pt) {return pt != 0;}); + vec.erase(itr, vec.end()); + std::reverse(vec.begin(), vec.end()); + return vec; +} + +#elif (defined(__linux__) || defined(__ANDROID__)) + +std::vector all_pids(boost::system::error_code & ec) +{ + std::vector vec; + DIR *proc = opendir("/proc"); + if (!proc) + { + ec = detail::get_last_error(); + return vec; + } + struct dirent *ent = nullptr; + while ((ent = readdir(proc))) + { + if (!isdigit(*ent->d_name)) + continue; + vec.push_back(atoi(ent->d_name)); + } + closedir(proc); + return vec; +} + +pid_type parent_pid(pid_type pid, boost::system::error_code & ec) +{ + pid_type ppid = static_cast(-1); + char buffer[BUFSIZ]; + sprintf(buffer, "/proc/%d/stat", pid); + FILE *stat = fopen(buffer, "r"); + if (!stat) + { + ec = detail::get_last_error(); + return ppid; + } + else + { + std::size_t size = fread(buffer, sizeof(char), sizeof(buffer), stat); + if (size > 0) + { + char *token = nullptr; + if ((token = strtok(buffer, " "))) + { + if ((token = strtok(nullptr, " "))) + { + if ((token = strtok(nullptr, " "))) + { + if ((token = strtok(nullptr, " "))) + { + ppid = (pid_type)strtoul(token, nullptr, 10); + } + } + } + } + if (!token) + { + fclose(stat); + ec = detail::get_last_error(); + return ppid; + } + } + fclose(stat); + } + return ppid; +} + +std::vector child_pids(pid_type pid, boost::system::error_code & ec) +{ + std::vector vec; + std::vector pids = all_pids(ec); + if (!pids.empty()) + vec.reserve(pids.size()); + for (std::size_t i = 0; i < pids.size(); i++) + { + pid_type ppid = parent_pid(pids[i], ec); + if (ppid != -1 && ppid == pid) + { + vec.push_back(pids[i]); + } + } + return vec; +} + +#elif defined(__FreeBSD__) + +std::vector all_pids(boost::system::error_code & ec) +{ + std::vector vec; + int cntp = 0; + kinfo_proc *proc_info = kinfo_getallproc(&cntp); + if (proc_info) + { + vec.reserve(cntp); + for (int i = 0; i < cntp; i++) + vec.push_back(proc_info[i].ki_pid); + free(proc_info); + } + else + ec = detail::get_last_error(); + return vec; +} + +pid_type parent_pid(pid_type pid, boost::system::error_code & ec) +{ + pid_type ppid = static_cast(-1); + kinfo_proc *proc_info = kinfo_getproc(pid); + if (proc_info) + { + ppid = proc_info->ki_ppid; + free(proc_info); + } + else + ec = detail::get_last_error(); + return ppid; +} + +std::vector child_pids(pid_type pid, boost::system::error_code & ec) +{ + std::vector vec; + int cntp = 0; + kinfo_proc *proc_info = kinfo_getallproc(&cntp); + if (proc_info) + { + vec.reserve(cntp); + for (int i = 0; i < cntp; i++) + { + if (proc_info[i].ki_ppid == pid) + { + vec.push_back(proc_info[i].ki_pid); + } + } + free(proc_info); + } + else + ec = detail::get_last_error(); + return vec; +} + +#elif defined(__DragonFly__) + +std::vector all_pids(boost::system::error_code & ec) +{ + std::vector vec; + int cntp = 0; + kinfo_proc *proc_info = nullptr; + const char *nlistf, *memf; + nlistf = memf = "/dev/null"; + struct closer + { + void operator()(kvm_t * kd) + { + kvm_close(kd); + } + }; + + std::unique_ptr kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)}; + if (!kd) + { + ec = detail::get_last_error(); + return vec; + } + if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, &cntp))) + { + vec.reserve(cntp); + for (int i = 0; i < cntp; i++) + if (proc_info[i].kp_pid >= 0) + vec.push_back(proc_info[i].kp_pid); + } + else + ec = detail::get_last_error(); + return vec; +} + +pid_type parent_pid(pid_type pid, boost::system::error_code & ec) +{ + pid_type ppid = static_cast(-1); + int cntp = 0; + kinfo_proc *proc_info = nullptr; + const char *nlistf, *memf; + nlistf = memf = "/dev/null"; + struct closer + { + void operator()(kvm_t * kd) + { + kvm_close(kd); + } + }; + + std::unique_ptr kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)}; + if (!kd) + { + ec = detail::get_last_error(); + return ppid; + } + if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_PID, pid, &cntp))) + { + if (proc_info->kp_ppid >= 0) + { + ppid = proc_info->kp_ppid; + } + } + else + ec = detail::get_last_error(); + return ppid; +} + +std::vector child_pids(pid_type pid, boost::system::error_code & ec) +{ + std::vector vec; + int cntp = 0; + kinfo_proc *proc_info = nullptr; + const char *nlistf, *memf; + nlistf = memf = "/dev/null"; + struct closer + { + void operator()(kvm_t * kd) + { + kvm_close(kd); + } + }; + + std::unique_ptr kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)}; + if (!kd) + { + ec = detail::get_last_error(); + return vec; + } + if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, &cntp))) + { + vec.reserve(cntp); + for (int i = 0; i < cntp; i++) + { + if (proc_info[i].kp_pid >= 0 && proc_info[i].kp_ppid >= 0 && proc_info[i].kp_ppid == pid) + { + vec.push_back(proc_info[i].kp_pid); + } + } + } + else + ec = detail::get_last_error(); + return vec; +} + +#elif defined(__NetBSD__) + +std::vector all_pids(boost::system::error_code & ec) +{ + std::vector vec; + int cntp = 0; + kinfo_proc2 *proc_info = nullptr; + struct closer + { + void operator()(kvm_t * kd) + { + kvm_close(kd); + } + }; + + std::unique_ptr kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)}; + if (!kd) + { + ec = detail::get_last_error(); + return vec; + } + if ((proc_info = kvm_getproc2(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &cntp))) + { + vec.reserve(cntp); + for (int i = cntp - 1; i >= 0; i--) + { + vec.push_back(proc_info[i].p_pid); + } + } + else + ec = detail::get_last_error(); + return vec; +} + +pid_type parent_pid(pid_type pid, boost::system::error_code & ec) +{ + pid_type ppid = static_cast(-1); + int cntp = 0; + kinfo_proc2 *proc_info = nullptr; + struct closer + { + void operator()(kvm_t * kd) + { + kvm_close(kd); + } + }; + + std::unique_ptr kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)}; + if (!kd) + { + ec = detail::get_last_error(); + return ppid; + } + if ((proc_info = kvm_getproc2(kd.get(), KERN_PROC_PID, pid, sizeof(struct kinfo_proc2), &cntp))) + { + ppid = proc_info->p_ppid; + } + else + ec = detail::get_last_error(); + return ppid; +} + +std::vector child_pids(pid_type pid, boost::system::error_code & ec) +{ + std::vector vec; + int cntp = 0; + kinfo_proc2 *proc_info = nullptr; + struct closer + { + void operator()(kvm_t * kd) + { + kvm_close(kd); + } + }; + + std::unique_ptr kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)}; + if (!kd) + { + ec = detail::get_last_error(); + return vec; + } + if ((proc_info = kvm_getproc2(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &cntp))) + { + vec.reserve(cntp); + for (int i = cntp - 1; i >= 0; i--) + { + if (proc_info[i].p_ppid == pid) + { + vec.push_back(proc_info[i].p_pid); + } + } + } + else + ec = detail::get_last_error(); + return vec; +} + +#elif defined(__OpenBSD__) + +std::vector all_pids(boost::system::error_code & ec) +{ + std::vector vec; + int cntp = 0; + kinfo_proc *proc_info = nullptr; + struct closer + { + void operator()(kvm_t * kd) + { + kvm_close(kd); + } + }; + + std::unique_ptr kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)}; + if (!kd) + { + ec = detail::get_last_error(); + return vec; + } + if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &cntp))) + { + vec.reserve(cntp); + for (int i = cntp - 1; i >= 0; i--) + { + if (proc_info[i].kp_pid >= 0) + { + vec.push_back(proc_info[i].kp_pid); + } + } + } + else + ec = detail::get_last_error(); + return vec; +} + +pid_type parent_pid(pid_type pid, boost::system::error_code & ec) +{ + pid_type ppid = static_cast(-1); + int cntp = 0; + kinfo_proc *proc_info = nullptr; + struct closer + { + void operator()(kvm_t * kd) + { + kvm_close(kd); + } + }; + + std::unique_ptr kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)}; + if (!kd) + { + ec = detail::get_last_error(); + return ppid; + } + if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &cntp))) + { + ppid = proc_info->p_ppid; + } + else + ec = detail::get_last_error(); + return ppid; +} + +std::vector child_pids(pid_type pid, boost::system::error_code & ec) +{ + std::vector vec; + int cntp = 0; + kinfo_proc *proc_info = nullptr; + struct closer + { + void operator()(kvm_t * kd) + { + kvm_close(kd); + } + }; + + std::unique_ptr kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)}; + if (!kd) + { + ec = detail::get_last_error(); + return vec; + } + if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &cntp))) + { + vec.reserve(cntp); + for (int i = cntp - 1; i >= 0; i--) + { + if (proc_info[i].p_ppid == pid) + { + vec.push_back(proc_info[i].p_pid); + } + } + } + else + ec = detail::get_last_error(); + return vec; +} + + +#elif defined(__sun) + +std::vector all_pids(boost::system::error_code & ec) +{ + std::vector vec; + struct pid cur_pid; + proc *proc_info = nullptr; + struct closer + { + void operator()(kvm_t * kd) + { + kvm_close(kd); + } + }; + + std::unique_ptr kd{kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr)}; + if (!kd) + { + ec = detail::get_last_error(); + return vec; + } + while ((proc_info = kvm_nextproc(kd))) + { + if (kvm_kread(kd, (std::uintptr_t)proc_info->p_pidp, &cur_pid, sizeof(cur_pid)) != -1) + { + vec.insert(vec.begin(), cur_pid.pid_id); + } + else + { + ec = detail::get_last_error(); + break; + } + } + return vec; +} + +pid_type parent_pid(pid_type pid, boost::system::error_code & ec) +{ + pid_type ppid = static_cast(-1); + proc *proc_info = nullptr; + struct closer + { + void operator()(kvm_t * kd) + { + kvm_close(kd); + } + }; + + std::unique_ptr kd{kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr)}; + if (!kd) + { + ec = detail::get_last_error(); + return ppid; + } + if ((proc_info = kvm_getproc(kd, pid))) + { + ppid = proc_info->p_ppid; + } + else + ec = detail::get_last_error(); + return ppid; +} + +std::vector child_pids(pid_type pid, boost::system::error_code & ec) +{ + std::vector vec; + struct pid cur_pid; + proc *proc_info = nullptr; + struct closer + { + void operator()(kvm_t * kd) + { + kvm_close(kd); + } + }; + + std::unique_ptr kd{kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr); + if (!kd) + { + ec = detail::get_last_error(); + return vec; + } + while ((proc_info = kvm_nextproc(kd))) + { + if (proc_info->p_ppid == pid) + { + if (kvm_kread(kd, (std::uintptr_t)proc_info->p_pidp, &cur_pid, sizeof(cur_pid)) != -1) + { + vec.insert(vec.begin(), cur_pid.pid_id); + } + else + { + ec = detail::get_last_error(); + break; + } + } + } + return vec; +} + +#else +#error "Platform not supported" +#endif + +std::vector all_pids() +{ + boost::system::error_code ec; + auto res = all_pids(ec); + if (ec) + detail::throw_error(ec, "all_pids"); + return res; +} + +pid_type parent_pid(pid_type pid) +{ + boost::system::error_code ec; + auto res = parent_pid(pid, ec); + if (ec) + detail::throw_error(ec, "parent_pid"); + return res; +} + +std::vector child_pids(pid_type pid) +{ + boost::system::error_code ec; + auto res = child_pids(pid, ec); + if (ec) + detail::throw_error(ec, "child_pids"); + return res; +} + BOOST_PROCESS_V2_END_NAMESPACE -#endif //BOOST_PROCESS_V2_IMPL_PID_IPP +#endif // BOOST_PROCESS_V2_IMPL_PID_IPP + diff --git a/include/boost/process/v2/impl/shell.ipp b/include/boost/process/v2/impl/shell.ipp index 1870297b..7a54f038 100644 --- a/include/boost/process/v2/impl/shell.ipp +++ b/include/boost/process/v2/impl/shell.ipp @@ -96,21 +96,23 @@ void shell::parse_() { argc_ = static_cast(we.we_wordc); argv_ = we.we_wordv; - reserved_ = static_cast(we.we_offs); } + + free_argv_ = +[](int argc, char ** argv) + { + wordexp_t we{ + .we_wordc = static_cast(argc), + .we_wordv = argv, + .we_offs = 0 + }; + wordfree(&we); + }; } shell::~shell() { - if (argv_ != nullptr) - { - wordexp_t we{ - .we_wordc = static_cast(argc_), - .we_wordv = argv_, - .we_offs = static_cast(reserved_) - }; - wordfree(&we); - } + if (argv_ != nullptr && free_argv_) + free_argv_(argc_, argv_); } auto shell::args() const -> args_type diff --git a/include/boost/process/v2/pid.hpp b/include/boost/process/v2/pid.hpp index 48a5e143..6f7baa04 100644 --- a/include/boost/process/v2/pid.hpp +++ b/include/boost/process/v2/pid.hpp @@ -1,4 +1,5 @@ // Copyright (c) 2022 Klemens D. Morgenstern +// Copyright (c) 2022 Samuel Venable // // 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) @@ -6,6 +7,7 @@ #define BOOST_PROCESS_V2_PID_HPP #include +#include BOOST_PROCESS_V2_BEGIN_NAMESPACE @@ -14,7 +16,6 @@ BOOST_PROCESS_V2_BEGIN_NAMESPACE //An integral type representing a process id. typedef implementation_defined pid_type; - #else #if defined(BOOST_PROCESS_V2_WINDOWS) @@ -28,14 +29,38 @@ typedef int pid_type; #endif #endif +#if (defined(BOOST_PROCESS_V2_WINDOWS) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(__sun)) +constexpr static pid_type root_pid = 0; +#elif (defined(__APPLE__) && defined(__MACH__) || defined(__linux__) || defined(__ANDROID__) || defined(__OpenBSD__)) +constexpr static pid_type root_pid = 1; +#endif + /// Get the process id of the current process. BOOST_PROCESS_V2_DECL pid_type current_pid(); +/// List all available pids. +BOOST_PROCESS_V2_DECL std::vector all_pids(boost::system::error_code & ec); + +/// List all available pids. +BOOST_PROCESS_V2_DECL std::vector all_pids(); + +// return parent pid of pid. +BOOST_PROCESS_V2_DECL pid_type parent_pid(pid_type pid, boost::system::error_code & ec); + +// return parent pid of pid. +BOOST_PROCESS_V2_DECL pid_type parent_pid(pid_type pid); + +// return child pids of pid. +BOOST_PROCESS_V2_DECL std::vector child_pids(pid_type pid, boost::system::error_code & ec); + +// return child pids of pid. +BOOST_PROCESS_V2_DECL std::vector child_pids(pid_type pid); + BOOST_PROCESS_V2_END_NAMESPACE #if defined(BOOST_PROCESS_V2_HEADER_ONLY) #include #endif +#endif // BOOST_PROCESS_V2_PID_HPP -#endif //BOOST_PROCESS_V2_PID_HPP diff --git a/include/boost/process/v2/process.hpp b/include/boost/process/v2/process.hpp index 798d1394..6c987a8b 100644 --- a/include/boost/process/v2/process.hpp +++ b/include/boost/process/v2/process.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #if defined(BOOST_PROCESS_V2_STANDALONE) @@ -214,6 +215,37 @@ struct basic_process process_handle_.request_exit(ec); } + /// Send the process a signal requesting it to stop. This may rely on undocmented 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. + void suspend() + { + error_code ec; + suspend(ec); + if (ec) + detail::throw_error(ec, "suspend"); + } + + + /// Send the process a signal requesting it to resume. This may rely on undocmented 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. + void resume() + { + error_code ec; + suspend(ec); + if (ec) + detail::throw_error(ec, "resume"); + } + /// Throwing @overload void terminate(native_exit_code_type &exit_code, error_code & ec) void terminate() { @@ -368,4 +400,4 @@ typedef basic_process<> process; BOOST_PROCESS_V2_END_NAMESPACE -#endif //BOOST_PROCESS_V2_PROCESS_HPP \ No newline at end of file +#endif //BOOST_PROCESS_V2_PROCESS_HPP diff --git a/include/boost/process/v2/shell.hpp b/include/boost/process/v2/shell.hpp index b58d2b41..a271f36c 100644 --- a/include/boost/process/v2/shell.hpp +++ b/include/boost/process/v2/shell.hpp @@ -79,8 +79,10 @@ struct shell : buffer_(std::move(lhs.buffer_)), input_(std::move(lhs.input_)), argc_(boost::exchange(lhs.argc_, 0)), - argv_(boost::exchange(lhs.argv_, nullptr)), - reserved_(boost::exchange(lhs.reserved_, 0)) + argv_(boost::exchange(lhs.argv_, nullptr)) +#if defined(BOOST_PROCESS_V2_POSIX) + , free_argv_(boost::exchange(lhs.free_argv_, nullptr)) +#endif { } shell& operator=(shell && lhs) noexcept @@ -90,7 +92,9 @@ struct shell input_ = std::move(lhs.input_); argc_ = boost::exchange(lhs.argc_, 0); argv_ = boost::exchange(lhs.argv_, nullptr); - reserved_ = boost::exchange(lhs.reserved_, 0); +#if defined(BOOST_PROCESS_V2_POSIX) + free_argv_ = boost::exchange(lhs.free_argv_, nullptr); +#endif return *this; } @@ -116,6 +120,9 @@ struct shell BOOST_PROCESS_V2_DECL ~shell(); private: + + friend struct make_cmd_shell_; + BOOST_PROCESS_V2_DECL void parse_(); // storage in case we need a conversion @@ -124,7 +131,10 @@ struct shell // impl details int argc_ = 0; char_type ** argv_ = nullptr; - int reserved_ = 0; + +#if defined(BOOST_PROCESS_V2_POSIX) + void(*free_argv_)(int, char **); +#endif }; diff --git a/include/boost/process/v2/src.hpp b/include/boost/process/v2/src.hpp index 9c3b3fb7..86470a4d 100644 --- a/include/boost/process/v2/src.hpp +++ b/include/boost/process/v2/src.hpp @@ -15,6 +15,11 @@ #include #include +#include +#include +#include +#include +#include #include #include #include diff --git a/test/v2/CMakeLists.txt b/test/v2/CMakeLists.txt index 51a1101e..4a27e6a7 100644 --- a/test/v2/CMakeLists.txt +++ b/test/v2/CMakeLists.txt @@ -1,11 +1,13 @@ enable_testing() add_library(boost_process_v2_test_impl test_impl.cpp) -target_link_libraries(boost_process_v2_test_impl Boost::process Boost::unit_test_framework Boost::process) target_compile_definitions(boost_process_v2_test_impl PUBLIC -DBOOST_PROCESS_V2_SEPARATE_COMPILATION=1) if (WIN32) target_compile_definitions(boost_process_v2_test_impl PUBLIC WIN32_LEAN_AND_MEAN=1) + target_link_libraries(boost_process_v2_test_impl Boost::process Boost::unit_test_framework Boost::process Ntdll) +else() + target_link_libraries(boost_process_v2_test_impl Boost::process Boost::unit_test_framework Boost::process) endif() function(boost_process_v2_standalone_test name) @@ -31,6 +33,9 @@ function(boost_process_v2_test_with_target name) add_dependencies(boost_process_v2_${name} boost_process_v2_test_target) add_test(NAME boost_process_v2_${name} COMMAND $ -- $) + + endfunction() -boost_process_v2_test_with_target(process) \ No newline at end of file +boost_process_v2_test_with_target(process) +boost_process_v2_test_with_target(ext) \ No newline at end of file diff --git a/test/v2/Jamfile.jam b/test/v2/Jamfile.jam index ef4a0679..f15cc1db 100644 --- a/test/v2/Jamfile.jam +++ b/test/v2/Jamfile.jam @@ -21,7 +21,12 @@ project : requirements msvc:_CRT_SECURE_NO_DEPRECATE msvc:/bigobj windows:WIN32_LEAN_AND_MEAN + windows:_WIN32_WINNT=0x0601 linux:-lpthread + freebsd:-lutil + freebsd:-lkvm + freebsd:-lprocstat + bsd:-lkvm NT,cw:ws2_32 NT,gcc:ws2_32 BOOST_PROCESS_V2_SEPARATE_COMPILATION=1 @@ -46,6 +51,8 @@ lib test_impl : test_impl.cpp filesystem : static windows:shell32 windows:user32 + windows:Ntdll + windows:Advapi32 ; test-suite standalone : @@ -59,5 +66,6 @@ test-suite standalone : 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 ] ; diff --git a/test/v2/ext.cpp b/test/v2/ext.cpp new file mode 100644 index 00000000..cab6ec13 --- /dev/null +++ b/test/v2/ext.cpp @@ -0,0 +1,173 @@ +// Copyright (c) 2022 Klemens D. Morgenstern +// Copyright (c) 2022 Samuel Venable +// +// 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 +#include +#include +#include +#include +#include +#include +#include + +BOOST_AUTO_TEST_SUITE(ext) + +BOOST_AUTO_TEST_CASE(test_exe) +{ + using boost::unit_test::framework::master_test_suite; + + 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_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]); + + boost::asio::io_context ctx; + bp2::process proc(ctx, pth, {"sleep", "10000"}); + BOOST_CHECK_EQUAL(bp2::ext::exe(proc.handle()), pth); +} + +BOOST_AUTO_TEST_CASE(cmd) +{ + using boost::unit_test::framework::master_test_suite; + + namespace bp2 = boost::process::v2; + auto cmd = bp2::ext::cmd(bp2::current_pid()); + + // the test framework drops a bunch of args. + bp2::basic_cstring_ref ref(cmd.argv()[0]); + BOOST_CHECK_EQUAL( + bp2::detail::conv_string( + ref.data(), ref.size() + ), master_test_suite().argv[0]); + + auto cm = cmd.argv() + (cmd.argc() - master_test_suite().argc); + for (auto i = 1; i < master_test_suite().argc; i++) + { + bp2::basic_cstring_ref ref(cm[i]); + + BOOST_CHECK_EQUAL(bp2::detail::conv_string(ref.data(), ref.size()), + master_test_suite().argv[i]); + } + +} + + +BOOST_AUTO_TEST_CASE(cmd_exe) +{ + using boost::unit_test::framework::master_test_suite; + const auto pth = master_test_suite().argv[1]; + + namespace bp2 = boost::process::v2; + + boost::asio::io_context ctx; + std::vector args = {"sleep", "10000", "moar", "args", " to test "}; + bp2::process proc(ctx, pth, args); + auto cm = bp2::ext::cmd(proc.handle()); + + bp2::basic_cstring_ref ref(cm.argv()[0]); + BOOST_CHECK_EQUAL(bp2::detail::conv_string(ref.data(), ref.size()), pth); + + BOOST_REQUIRE_EQUAL(cm.argc(), args.size() + 1); + for (auto i = 0; i < args.size(); i++) + { + ref = cm.argv()[i + 1]; + + BOOST_CHECK_EQUAL(bp2::detail::conv_string(ref.data(), ref.size()), args[i]); + } + +} + + +BOOST_AUTO_TEST_CASE(test_cwd) +{ + namespace bp2 = boost::process::v2; + auto pth = bp2::ext::cwd(bp2::current_pid()).string(); + if (pth.back() == '\\') + pth.pop_back(); + BOOST_CHECK_EQUAL(pth, bp2::filesystem::current_path()); +} + +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; + + auto tmp = bp2::filesystem::temp_directory_path(); + + boost::asio::io_context ctx; + bp2::process proc(ctx, pth, {"sleep", "10000"}, + bp2::process_start_dir{tmp}); + auto tt = bp2::ext::cwd(proc.handle()).string(); + if (tt.back() == '\\') + tt.pop_back(); + BOOST_CHECK_EQUAL(tt, tmp); + bp2::error_code ec; + bp2::filesystem::remove(tmp, ec); +} + +BOOST_AUTO_TEST_CASE(test_env) +{ + namespace bp2 = boost::process::v2; + auto env = bp2::ext::env(bp2::current_pid()); + + + for (const auto & kp : bp2::environment::current()) + { + auto itr = std::find_if(env.begin(), env.end(), + [&](bp2::environment::key_value_pair_view kp_) + { + return kp.key() == kp_.key(); + }); + BOOST_REQUIRE(itr != env.end()); + BOOST_CHECK_EQUAL(kp.value(), (*itr).value()); + } +} + +BOOST_AUTO_TEST_CASE(test_env_exe) +{ + using boost::unit_test::framework::master_test_suite; + const auto pth = master_test_suite().argv[1]; + namespace bp2 = boost::process::v2; + + auto tmp = bp2::filesystem::temp_directory_path(); + + boost::asio::io_context ctx; + + std::vector new_env; + { + auto cr = bp2::environment::current(); + new_env.assign(cr.begin(), cr.end()); + } + + new_env.push_back("FOO=42"); + new_env.push_back("BAR=FOO"); + + bp2::process proc(ctx, pth, {"sleep", "10000"}, + bp2::process_environment(new_env)); + + auto env = bp2::ext::env(proc.handle()); + for (const auto & kp : new_env) + { + auto itr = std::find_if(env.begin(), env.end(), + [&](bp2::environment::key_value_pair_view kp_) + { + return kp.key() == kp_.key(); + }); + BOOST_REQUIRE(itr != env.end()); + BOOST_CHECK_EQUAL(kp.value(), (*itr).value()); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/v2/pid.cpp b/test/v2/pid.cpp index a0664bcc..ae1841a9 100644 --- a/test/v2/pid.cpp +++ b/test/v2/pid.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2022 Klemens D. Morgenstern +// Copyright (c) 2022 Samuel Venable // // 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) @@ -7,9 +8,32 @@ #include +#include +#include BOOST_AUTO_TEST_CASE(test_pid) { namespace bp2 = boost::process::v2; BOOST_CHECK_NE(bp2::current_pid(), static_cast(0)); -} \ No newline at end of file + + auto all = bp2::all_pids(); + auto itr = std::find(all.begin(), all.end(), bp2::current_pid()); + BOOST_CHECK(itr != all.end()); + + std::vector children, grand_children; + auto grand_child_pids = [](bp2::pid_type pid, + std::vector & children, + std::vector & grand_children) + { + children = bp2::child_pids(pid); + for (unsigned i = 0; i < children.size(); i++) + { + std::vector tmp1; + std::vector tmp2 = bp2::child_pids(children[i]); + tmp1.insert(std::end(tmp1), std::begin(tmp2), std::end(tmp2)); + grand_children = tmp1; + } + return (!children.empty() || !grand_children.empty()); + }; + BOOST_CHECK_NE(grand_child_pids(bp2::root_pid, children, grand_children), false); +} diff --git a/test/v2/process.cpp b/test/v2/process.cpp index e1c142c0..703e820e 100644 --- a/test/v2/process.cpp +++ b/test/v2/process.cpp @@ -150,6 +150,8 @@ BOOST_AUTO_TEST_CASE(terminate) BOOST_CHECK_MESSAGE(!sh.empty(), sh); bpv::process proc(ctx, sh, {}); + proc.suspend(); + proc.resume(); proc.terminate(); proc.wait(); } From 9d51e1cd32826d1057fff4728f7fc0ca2c61e886 Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Mon, 6 Feb 2023 20:50:00 +0800 Subject: [PATCH 17/27] xproc fixes --- doc/acknowledgements.qbk | 2 + include/boost/process/environment.hpp | 2 +- .../v2/detail/process_handle_signal.hpp | 5 +- include/boost/process/v2/ext.hpp | 16 +++ include/boost/process/v2/ext/cmd.hpp | 13 +- include/boost/process/v2/ext/cwd.hpp | 36 ++++-- include/boost/process/v2/ext/env.hpp | 40 ++++-- include/boost/process/v2/ext/exe.hpp | 23 +++- include/boost/process/v2/ext/impl/cmd.ipp | 18 +-- include/boost/process/v2/ext/impl/cwd.ipp | 6 +- include/boost/process/v2/ext/impl/env.ipp | 122 ++++++++++++++++-- include/boost/process/v2/ext/impl/exe.ipp | 3 +- include/boost/process/v2/impl/pid.ipp | 2 +- include/boost/process/v2/impl/shell.ipp | 2 +- include/boost/process/v2/process.hpp | 8 +- test/v2/Jamfile.jam | 4 +- test/v2/ext.cpp | 21 ++- test/v2/pid.cpp | 5 + test/v2/process.cpp | 19 ++- 19 files changed, 266 insertions(+), 81 deletions(-) create mode 100644 include/boost/process/v2/ext.hpp 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, From e4a3e305b44c80378d0e00f4cc5b3ba0aedd01f5 Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Tue, 7 Feb 2023 15:48:11 +0800 Subject: [PATCH 18/27] ec use locations. --- include/boost/process/v2/cstring_ref.hpp | 2 +- include/boost/process/v2/detail/config.hpp | 29 +++++++- .../v2/detail/impl/environment_posix.ipp | 6 +- .../v2/detail/impl/environment_win.ipp | 12 ++-- .../process/v2/detail/impl/last_error.ipp | 14 ---- .../v2/detail/impl/process_handle_windows.ipp | 31 ++++---- include/boost/process/v2/detail/impl/utf8.ipp | 20 +++--- .../boost/process/v2/detail/last_error.hpp | 7 +- include/boost/process/v2/exit_code.hpp | 2 +- .../process/v2/ext/detail/impl/proc_info.ipp | 10 +-- include/boost/process/v2/ext/impl/cmd.ipp | 44 ++++++------ include/boost/process/v2/ext/impl/cwd.ipp | 18 ++--- include/boost/process/v2/ext/impl/env.ipp | 22 +++--- include/boost/process/v2/ext/impl/exe.ipp | 10 +-- include/boost/process/v2/impl/pid.ipp | 72 +++++++++---------- include/boost/process/v2/impl/shell.ipp | 6 +- .../process/v2/posix/default_launcher.hpp | 12 ++-- .../v2/posix/fork_and_forget_launcher.hpp | 4 +- .../process/v2/posix/pdfork_launcher.hpp | 12 ++-- .../boost/process/v2/posix/vfork_launcher.hpp | 4 +- include/boost/process/v2/stdio.hpp | 10 ++- .../process/v2/windows/as_user_launcher.hpp | 2 +- .../process/v2/windows/default_launcher.hpp | 2 +- .../v2/windows/with_logon_launcher.hpp | 2 +- .../v2/windows/with_token_launcher.hpp | 2 +- test/v2/pid.cpp | 2 - 26 files changed, 189 insertions(+), 168 deletions(-) diff --git a/include/boost/process/v2/cstring_ref.hpp b/include/boost/process/v2/cstring_ref.hpp index 72c54448..42a374f4 100644 --- a/include/boost/process/v2/cstring_ref.hpp +++ b/include/boost/process/v2/cstring_ref.hpp @@ -106,7 +106,7 @@ struct basic_cstring_ref BOOST_CXX14_CONSTEXPR const_reference at(size_type pos) const { if (pos >= size()) - throw std::out_of_range("cstring-view out of range"); + throw_exception(std::out_of_range("cstring-view out of range")); return view_[pos]; } BOOST_CONSTEXPR const_reference front() const {return *view_;} diff --git a/include/boost/process/v2/detail/config.hpp b/include/boost/process/v2/detail/config.hpp index 4febb8ca..0c985d18 100644 --- a/include/boost/process/v2/detail/config.hpp +++ b/include/boost/process/v2/detail/config.hpp @@ -97,6 +97,14 @@ namespace filesystem = std::filesystem; using std::quoted; using std::optional; +#define BOOST_PROCESS_V2_RETURN_EC(ev) \ + return ::BOOST_PROCESS_V2_NAMESPACE::error_code(ev, ::BOOST_PROCESS_V2_NAMESPACE::system_category()); \ + +#define BOOST_PROCESS_V2_ASSIGN_EC(ec, ...) ec.assign(__VA_ARGS__); +#define BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) \ + ec.assign(::BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error()); \ + + #else using boost::system::error_code ; @@ -112,6 +120,25 @@ namespace filesystem = std::filesystem; namespace filesystem = boost::filesystem; #endif +#define BOOST_PROCESS_V2_RETURN_EC(ev) \ +{ \ + static constexpr auto loc##__LINE__((BOOST_CURRENT_LOCATION)); \ + return ::BOOST_PROCESS_V2_NAMESPACE::error_code(ev, ::BOOST_PROCESS_V2_NAMESPACE::system_category(), &loc##__LINE__); \ +} + +#define BOOST_PROCESS_V2_ASSIGN_EC(ec, ...) \ +{ \ + static constexpr auto loc##__LINE__((BOOST_CURRENT_LOCATION)); \ + ec.assign(__VA_ARGS__, &loc##__LINE__); \ +} + +#define BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) \ +{ \ + static constexpr auto loc##__LINE__((BOOST_CURRENT_LOCATION)); \ + ec.assign(::BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error(), &loc##__LINE__); \ +} + + #endif BOOST_PROCESS_V2_END_NAMESPACE @@ -150,6 +177,4 @@ BOOST_PROCESS_V2_END_NAMESPACE #define BOOST_PROCESS_V2_HAS_PROCESS_HANDLE 1 #endif - - #endif //BOOST_PROCESS_V2_DETAIL_CONFIG_HPP diff --git a/include/boost/process/v2/detail/impl/environment_posix.ipp b/include/boost/process/v2/detail/impl/environment_posix.ipp index 7d9ad564..0f76b816 100644 --- a/include/boost/process/v2/detail/impl/environment_posix.ipp +++ b/include/boost/process/v2/detail/impl/environment_posix.ipp @@ -34,7 +34,7 @@ basic_cstring_ref> get( auto res = ::getenv(key.c_str()); if (res == nullptr) { - ec.assign(ENOENT, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, ENOENT, system_category()) return {}; } return res; @@ -45,13 +45,13 @@ void set(basic_cstring_ref> key, error_code & ec) { if (::setenv(key.c_str(), value.c_str(), true)) - ec = ::BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } void unset(basic_cstring_ref> key, error_code & ec) { if (::unsetenv(key.c_str())) - ec = ::BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } diff --git a/include/boost/process/v2/detail/impl/environment_win.ipp b/include/boost/process/v2/detail/impl/environment_win.ipp index 37e72dc2..86792f2e 100644 --- a/include/boost/process/v2/detail/impl/environment_win.ipp +++ b/include/boost/process/v2/detail/impl/environment_win.ipp @@ -50,7 +50,7 @@ std::basic_string> get( buf.resize(size); if (buf.size() == 0) - ec = ::BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return buf; } @@ -60,14 +60,14 @@ void set(basic_cstring_ref> key, error_code & ec) { if (!::SetEnvironmentVariableW(key.c_str(), value.c_str())) - ec = ::BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } void unset(basic_cstring_ref> key, error_code & ec) { if (!::SetEnvironmentVariableW(key.c_str(), nullptr)) - ec = ::BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } @@ -88,7 +88,7 @@ std::basic_string> get( buf.resize(size); if (buf.size() == 0) - ec = ::BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return buf; } @@ -98,14 +98,14 @@ void set(basic_cstring_ref> key, error_code & ec) { if (!::SetEnvironmentVariableA(key.c_str(), value.c_str())) - ec = ::BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } void unset(basic_cstring_ref> key, error_code & ec) { if (!::SetEnvironmentVariableA(key.c_str(), nullptr)) - ec = ::BOOST_PROCESS_V2_NAMESPACE::detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } diff --git a/include/boost/process/v2/detail/impl/last_error.ipp b/include/boost/process/v2/detail/impl/last_error.ipp index f9c294c2..8254fdb6 100644 --- a/include/boost/process/v2/detail/impl/last_error.ipp +++ b/include/boost/process/v2/detail/impl/last_error.ipp @@ -28,20 +28,6 @@ error_code get_last_error() } -void throw_last_error() -{ - throw system_error(get_last_error()); -} -void throw_last_error(const char * msg) -{ - throw system_error(get_last_error(), msg); -} -void throw_last_error(const std::string & msg) -{ - throw system_error(get_last_error(), msg); -} - - } BOOST_PROCESS_V2_END_NAMESPACE diff --git a/include/boost/process/v2/detail/impl/process_handle_windows.ipp b/include/boost/process/v2/detail/impl/process_handle_windows.ipp index 638bc014..535bc011 100644 --- a/include/boost/process/v2/detail/impl/process_handle_windows.ipp +++ b/include/boost/process/v2/detail/impl/process_handle_windows.ipp @@ -34,7 +34,7 @@ void get_exit_code_( error_code & ec) { if (!::GetExitCodeProcess(handle, &exit_code)) - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } @@ -42,7 +42,12 @@ HANDLE open_process_(DWORD pid) { auto proc = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, FALSE, pid); if (proc == nullptr) - detail::throw_last_error("open_process()"); + { + error_code ec; + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) + throw system_error(ec, "open_process()"); + } + return proc; } @@ -61,7 +66,7 @@ bool check_handle_(HANDLE handle, error_code & ec) { if (handle == INVALID_HANDLE_VALUE) { - ec.assign(ERROR_INVALID_HANDLE_STATE, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, ERROR_INVALID_HANDLE_STATE, system_category()) return false; } return true; @@ -71,7 +76,7 @@ bool check_pid_(pid_type pid_, error_code & ec) { if (pid_ == 0) { - ec.assign(ERROR_INVALID_HANDLE_STATE, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, ERROR_INVALID_HANDLE_STATE, system_category()) return false; } return true; @@ -94,7 +99,7 @@ static BOOL CALLBACK enum_window(HWND hwnd, LPARAM param) LRESULT res = ::SendMessageW(hwnd, WM_CLOSE, 0, 0); if (res) - data->ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(data->ec) return res == 0; } @@ -103,25 +108,25 @@ void request_exit_(pid_type pid_, error_code & ec) enum_windows_data_t data{ec, pid_}; if (!::EnumWindows(enum_window, reinterpret_cast(&data))) - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } void interrupt_(pid_type pid_, error_code & ec) { if (!::GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid_)) - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } void terminate_(HANDLE handle, error_code & ec, DWORD & exit_status) { if (!::TerminateProcess(handle, 260)) - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } void check_running_(HANDLE handle, error_code & ec, DWORD & exit_status) { if (!::GetExitCodeProcess(handle, &exit_status)) - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } #if !defined(BOOST_PROCESS_V2_DISABLE_UNDOCUMENTED_API) @@ -130,7 +135,7 @@ void suspend_(HANDLE handle, error_code & ec) auto nt_err = NtSuspendProcess(handle); ULONG dos_err = RtlNtStatusToDosError(nt_err); if (dos_err) - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } void resume_(HANDLE handle, error_code & ec) @@ -138,17 +143,17 @@ void resume_(HANDLE handle, error_code & ec) auto nt_err = NtResumeProcess(handle); ULONG dos_err = RtlNtStatusToDosError(nt_err); if (dos_err) - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } #else void suspend_(HANDLE, error_code & ec) { - ec.assign(ERROR_CALL_NOT_IMPLEMENTED, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, ERROR_CALL_NOT_IMPLEMENTED, system_category()) } void resume_(HANDLE handle, error_code & ec) { - ec.assign(ERROR_CALL_NOT_IMPLEMENTED, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, ERROR_CALL_NOT_IMPLEMENTED, system_category()) } #endif diff --git a/include/boost/process/v2/detail/impl/utf8.ipp b/include/boost/process/v2/detail/impl/utf8.ipp index 22623df6..5a3c2091 100644 --- a/include/boost/process/v2/detail/impl/utf8.ipp +++ b/include/boost/process/v2/detail/impl/utf8.ipp @@ -27,13 +27,13 @@ inline void handle_error(error_code & ec) switch (err) { case ERROR_INSUFFICIENT_BUFFER: - ec.assign(error::insufficient_buffer, error::utf8_category); + BOOST_PROCESS_V2_ASSIGN_EC(ec, error::insufficient_buffer, error::utf8_category) break; case ERROR_NO_UNICODE_TRANSLATION: - ec.assign(error::invalid_character, error::utf8_category); + BOOST_PROCESS_V2_ASSIGN_EC(ec, error::invalid_character, error::utf8_category) break; default: - ec.assign(err, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, err, system_category()) } } @@ -242,7 +242,7 @@ std::size_t convert_to_utf8(const wchar_t * in, std::size_t size, if (*from > max_wchar) { from_next = from; to_next = to; - ec.assign(error::invalid_character, error::get_utf8_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, error::invalid_character, error::get_utf8_category()) return 0u; } @@ -270,7 +270,7 @@ std::size_t convert_to_utf8(const wchar_t * in, std::size_t size, if (to == to_end && i != cont_octet_count) { from_next = from; to_next = to - (i + 1); - ec.assign(error::insufficient_buffer, error::get_utf8_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, error::insufficient_buffer, error::get_utf8_category()) return 0u; } ++from; @@ -280,7 +280,7 @@ std::size_t convert_to_utf8(const wchar_t * in, std::size_t size, // Were we done or did we run out of destination space if (from != from_end) - ec.assign(error::insufficient_buffer, error::get_utf8_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, error::insufficient_buffer, error::get_utf8_category()) return to_next - out; } @@ -315,7 +315,7 @@ std::size_t convert_to_wide(const char * in, std::size_t size, if (invalid_leading_octet(*from)) { from_next = from; to_next = to; - ec.assign(error::invalid_character, error::get_utf8_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, error::invalid_character, error::get_utf8_category()) return 0u; } @@ -339,7 +339,7 @@ std::size_t convert_to_wide(const char * in, std::size_t size, if (invalid_continuing_octet(*from)) { from_next = from; to_next = to; - ec.assign(error::invalid_character, error::get_utf8_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, error::invalid_character, error::get_utf8_category()) return 0u; } @@ -356,7 +356,7 @@ std::size_t convert_to_wide(const char * in, std::size_t size, // rewind "from" to before the current character translation from_next = from - (i + 1); to_next = to; - ec.assign(error::insufficient_buffer, error::get_utf8_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, error::insufficient_buffer, error::get_utf8_category()) return 0u; } *to++ = ucs_result; @@ -365,7 +365,7 @@ std::size_t convert_to_wide(const char * in, std::size_t size, to_next = to; if (from != from_end) - ec.assign(error::insufficient_buffer, error::get_utf8_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, error::insufficient_buffer, error::get_utf8_category()) return to_next - out; } diff --git a/include/boost/process/v2/detail/last_error.hpp b/include/boost/process/v2/detail/last_error.hpp index 05e09ee0..6b2d70f6 100644 --- a/include/boost/process/v2/detail/last_error.hpp +++ b/include/boost/process/v2/detail/last_error.hpp @@ -9,14 +9,13 @@ BOOST_PROCESS_V2_BEGIN_NAMESPACE -namespace detail { +namespace detail +{ BOOST_PROCESS_V2_DECL error_code get_last_error(); -BOOST_PROCESS_V2_DECL void throw_last_error(); -BOOST_PROCESS_V2_DECL void throw_last_error(const char * msg); -BOOST_PROCESS_V2_DECL void throw_last_error(const std::string & msg); } + BOOST_PROCESS_V2_END_NAMESPACE #if defined(BOOST_PROCESS_V2_HEADER_ONLY) diff --git a/include/boost/process/v2/exit_code.hpp b/include/boost/process/v2/exit_code.hpp index 5ac30703..3835d9f9 100644 --- a/include/boost/process/v2/exit_code.hpp +++ b/include/boost/process/v2/exit_code.hpp @@ -148,7 +148,7 @@ struct code_as_error_handler void operator()(error_code ec, native_exit_code_type code) { if (!ec) - ec.assign(code, category); + BOOST_PROCESS_V2_ASSIGN_EC(ec, code, category) std::move(handler_)(ec); } diff --git a/include/boost/process/v2/ext/detail/impl/proc_info.ipp b/include/boost/process/v2/ext/detail/impl/proc_info.ipp index ba866735..4de38dad 100644 --- a/include/boost/process/v2/ext/detail/impl/proc_info.ipp +++ b/include/boost/process/v2/ext/detail/impl/proc_info.ipp @@ -48,19 +48,19 @@ std::wstring cwd_cmd_from_proc(HANDLE proc, int type, boost::system::error_code if (error) { - ec.assign(error, boost::system::system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, error, boost::system::system_category()) return {}; } if (!ReadProcessMemory(proc, pbi.PebBaseAddress, &peb, sizeof(peb), &nRead)) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {}; } if (!ReadProcessMemory(proc, peb.ProcessParameters, &upp, sizeof(upp), &nRead)) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {}; } @@ -79,7 +79,7 @@ std::wstring cwd_cmd_from_proc(HANDLE proc, int type, boost::system::error_code if (!ReadProcessMemory(proc, buf, &buffer[0], len, &nRead)) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {}; } @@ -112,7 +112,7 @@ HANDLE open_process_with_debug_privilege(boost::process::v2::pid_type pid, boost if (!proc) proc = OpenProcess(PROCESS_ALL_ACCESS, false, pid); if (!proc) - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return proc; } #endif diff --git a/include/boost/process/v2/ext/impl/cmd.ipp b/include/boost/process/v2/ext/impl/cmd.ipp index efe20193..614e6919 100644 --- a/include/boost/process/v2/ext/impl/cmd.ipp +++ b/include/boost/process/v2/ext/impl/cmd.ipp @@ -146,7 +146,7 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) }; std::unique_ptr proc{detail::ext::open_process_with_debug_privilege(pid, ec)}; if (proc == nullptr) - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) else return cmd(proc.get(), ec); @@ -161,7 +161,7 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) auto size = sizeof(argmax); if (sysctl(mib, 2, &argmax, &size, nullptr, 0) == -1) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {}; } @@ -174,7 +174,7 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) if (sysctl(mib, 3, &*procargs.begin(), &size, nullptr, 0) != 0) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {}; } @@ -191,7 +191,7 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) auto e = std::find(itr, end, '\0'); if (e == end && n < argc) // something off { - ec.assign(EINVAL, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, EINVAL, system_category()) return {}; } argv[n] = &*itr; @@ -216,7 +216,7 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) auto r = ::read(f, &*(procargs.end() - 4096), 4096); if (r < 0) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) ::close(f); return {}; } @@ -247,7 +247,7 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) auto e = std::find(itr, end, '\0'); if (e == end && n < argc) // something off { - ec.assign(EINVAL, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, EINVAL, system_category()) return {}; } argv[n] = &*itr; @@ -273,7 +273,7 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) std::unique_ptr proc_stat{procstat_open_sysctl()}; if (!proc_stat) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {}; } @@ -294,14 +294,14 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) if (!proc_info) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {}; } char **cmd = procstat_getargv(proc_stat.get(), proc_info.get(), 0); if (!cmd) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {}; } auto res = make_cmd_shell_::clone(cmd); @@ -326,17 +326,17 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) }; std::unique_ptr kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)}; - if (!kd) {ec = detail::get_last_error(); return {};} + if (!kd) {BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {};} if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_PID, pid, &cntp))) { char **cmd = kvm_getargv(kd.get(), proc_info, 0); if (cmd) return make_cmd_shell_::clone(cmd); else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {}; } @@ -358,17 +358,17 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) std::unique_ptr kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)}; - if (!kd) {ec = detail::get_last_error(); return vec;} + if (!kd) {BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec;} if ((proc_info = kvm_getproc2(kd.get(), KERN_PROC_PID, pid, sizeof(struct kinfo_proc2), &cntp))) { char **cmd = kvm_getargv2(kd.get(), proc_info, 0); if (cmd) return make_cmd_shell_::clone(cmd); else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } @@ -389,17 +389,17 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) }; std::unique_ptr kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)}; - if (!kd) {ec = detail::get_last_error(); return vec;} + if (!kd) {BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec;} if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &cntp))) { char **cmd = kvm_getargv(kd.get(), proc_info, 0); if (cmd) return make_cmd_shell_::clone(cmd); else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) kvm_close(kd); return {}; } @@ -412,7 +412,7 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) proc *proc_info = nullptr; user *proc_user = nullptr; kd = kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr); - if (!kd) {ec = detail::get_last_error(); return {};} + if (!kd) {BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {};} if ((proc_info = kvm_getproc(kd, pid))) { if ((proc_user = kvm_getu(kd, proc_info))) @@ -427,13 +427,13 @@ shell cmd(boost::process::v2::pid_type pid, boost::system::error_code & ec) +[](int, char ** argv) {::free(argv);}) } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) kvm_close(kd); return {}; diff --git a/include/boost/process/v2/ext/impl/cwd.ipp b/include/boost/process/v2/ext/impl/cwd.ipp index 0afb14c1..a73dbbcd 100644 --- a/include/boost/process/v2/ext/impl/cwd.ipp +++ b/include/boost/process/v2/ext/impl/cwd.ipp @@ -66,7 +66,7 @@ filesystem::path cwd(HANDLE proc, boost::system::error_code & ec) if (!buffer.empty()) return filesystem::canonical(buffer, ec); else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ""; } @@ -81,7 +81,7 @@ filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code }; std::unique_ptr proc{detail::ext::open_process_with_debug_privilege(pid, ec)}; if (proc == nullptr) - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) else return cwd(proc.get(), ec); return {}; @@ -104,7 +104,7 @@ filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code if (proc_pidinfo(pid, PROC_PIDVNODEPATHINFO, 0, &vpi, sizeof(vpi)) > 0) return filesystem::canonical(vpi.pvi_cdir.vip_path, ec); else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ""; } @@ -139,15 +139,15 @@ filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code procstat_freefiles(proc_stat, head); } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) procstat_freeprocs(proc_stat, proc_info); } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) procstat_close(proc_stat); } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return path; } @@ -177,11 +177,11 @@ filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code path = filesystem::canonical(str.c_str(), ec); } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) pclose(fp); } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return path; } @@ -207,7 +207,7 @@ filesystem::path cwd(boost::process::v2::pid_type pid, boost::system::error_code filesystem::canonical(strbuff, ec); } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } return ""; diff --git a/include/boost/process/v2/ext/impl/env.ipp b/include/boost/process/v2/ext/impl/env.ipp index e4eee7dc..a6d87e6f 100644 --- a/include/boost/process/v2/ext/impl/env.ipp +++ b/include/boost/process/v2/ext/impl/env.ipp @@ -153,19 +153,19 @@ env_view env(HANDLE proc, boost::system::error_code & ec) if (error) { - ec.assign(error, boost::system::system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, error, boost::system::system_category()) return {}; } if (!ReadProcessMemory(proc, pbi.PebBaseAddress, &peb, sizeof(peb), &nRead)) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {}; } if (!ReadProcessMemory(proc, peb.ProcessParameters, &upp, sizeof(upp), &nRead)) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {}; } @@ -176,7 +176,7 @@ env_view env(HANDLE proc, boost::system::error_code & ec) if (!ReadProcessMemory(proc, buf, ev.handle_.get(), len, &nRead)) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {}; } @@ -204,7 +204,7 @@ env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec) }; std::unique_ptr proc{detail::ext::open_process_with_debug_privilege(pid, ec)}; if (proc == nullptr) - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) else return env(proc.get(), ec); @@ -220,7 +220,7 @@ env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec) auto size = sizeof(argmax); if (sysctl(mib, 2, &argmax, &size, nullptr, 0) == -1) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {}; } @@ -233,7 +233,7 @@ env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec) if (sysctl(mib, 3, &*procargs.begin(), &size, nullptr, 0) != 0) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {}; } std::uint32_t nargs; @@ -291,7 +291,7 @@ env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec) auto r = ::read(f, buf.get() + size, 4096); if (r < 0) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) ::close(f); return {}; } @@ -358,18 +358,18 @@ env_view env(boost::process::v2::pid_type pid, boost::system::error_code & ec) ev.handle_.reset(eeo); } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } procstat_freeprocs(proc_stat, proc_info); } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) procstat_close(proc_stat); } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ev; } diff --git a/include/boost/process/v2/ext/impl/exe.ipp b/include/boost/process/v2/ext/impl/exe.ipp index 18f981bc..8b5bd993 100644 --- a/include/boost/process/v2/ext/impl/exe.ipp +++ b/include/boost/process/v2/ext/impl/exe.ipp @@ -77,7 +77,7 @@ filesystem::path exe(HANDLE proc, boost::system::error_code & ec) return filesystem::canonical(buffer, ec); } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ""; } @@ -103,7 +103,7 @@ filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code }; std::unique_ptr proc{detail::ext::open_process_with_debug_privilege(pid, ec)}; if (proc == nullptr) - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) else return exe(proc.get(), ec); } @@ -119,7 +119,7 @@ filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code { return filesystem::canonical(buffer, ec); } - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ""; } @@ -159,7 +159,7 @@ filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code } } - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ""; } @@ -167,7 +167,7 @@ filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code filesystem::path exe(boost::process::v2::pid_type pid, boost::system::error_code & ec) { - ec.assign(ENOTSUP, boost::system::system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, ENOTSUP, boost::system::system_category()) return ""; } diff --git a/include/boost/process/v2/impl/pid.ipp b/include/boost/process/v2/impl/pid.ipp index aa3d164b..61e848bb 100644 --- a/include/boost/process/v2/impl/pid.ipp +++ b/include/boost/process/v2/impl/pid.ipp @@ -73,7 +73,7 @@ std::vector all_pids(boost::system::error_code & ec) HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (!hp) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } PROCESSENTRY32 pe; @@ -95,7 +95,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec) HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (!hp) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ppid; } PROCESSENTRY32 pe; @@ -122,7 +122,7 @@ std::vector child_pids(pid_type pid, boost::system::error_code & ec) HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (!hp) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } PROCESSENTRY32 pe; @@ -150,7 +150,7 @@ std::vector all_pids(boost::system::error_code & ec) vec.reserve(proc_listpids(PROC_ALL_PIDS, 0, nullptr, 0)); if (proc_listpids(PROC_ALL_PIDS, 0, &vec[0], sizeof(pid_type) * vec.size())) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {}; } auto itr = std::partition(vec.begin(), vec.end(), [](pid_type pt) {return pt != 0;}); @@ -165,7 +165,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec) proc_bsdinfo proc_info; if (proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &proc_info, sizeof(proc_info)) <= 0) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ppid; } else @@ -179,7 +179,7 @@ std::vector child_pids(pid_type pid, boost::system::error_code & ec) vec.reserve(proc_listpids(PROC_PPID_ONLY, (uint32_t)pid, nullptr, 0)); if (proc_listpids(PROC_PPID_ONLY, (uint32_t)pid, &vec[0], sizeof(pid_type) * vec.size())) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {}; } auto itr = std::partition(vec.begin(), vec.end(), [](pid_type pt) {return pt != 0;}); @@ -196,7 +196,7 @@ std::vector all_pids(boost::system::error_code & ec) DIR *proc = opendir("/proc"); if (!proc) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } struct dirent *ent = nullptr; @@ -218,7 +218,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec) FILE *stat = fopen(buffer, "r"); if (!stat) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ppid; } else @@ -243,7 +243,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec) if (!token) { fclose(stat); - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ppid; } } @@ -284,7 +284,7 @@ std::vector all_pids(boost::system::error_code & ec) free(proc_info); } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } @@ -298,7 +298,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec) free(proc_info); } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ppid; } @@ -320,7 +320,7 @@ std::vector child_pids(pid_type pid, boost::system::error_code & ec) free(proc_info); } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } @@ -344,7 +344,7 @@ std::vector all_pids(boost::system::error_code & ec) std::unique_ptr kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)}; if (!kd) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, &cntp))) @@ -355,7 +355,7 @@ std::vector all_pids(boost::system::error_code & ec) vec.push_back(proc_info[i].kp_pid); } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } @@ -377,7 +377,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec) std::unique_ptr kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)}; if (!kd) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ppid; } if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_PID, pid, &cntp))) @@ -388,7 +388,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec) } } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ppid; } @@ -410,7 +410,7 @@ std::vector child_pids(pid_type pid, boost::system::error_code & ec) std::unique_ptr kd{kvm_openfiles(nlistf, memf, nullptr, O_RDONLY, nullptr)}; if (!kd) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, &cntp))) @@ -425,7 +425,7 @@ std::vector child_pids(pid_type pid, boost::system::error_code & ec) } } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } @@ -447,7 +447,7 @@ std::vector all_pids(boost::system::error_code & ec) std::unique_ptr kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)}; if (!kd) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } if ((proc_info = kvm_getproc2(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &cntp))) @@ -459,7 +459,7 @@ std::vector all_pids(boost::system::error_code & ec) } } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } @@ -479,7 +479,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec) std::unique_ptr kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)}; if (!kd) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ppid; } if ((proc_info = kvm_getproc2(kd.get(), KERN_PROC_PID, pid, sizeof(struct kinfo_proc2), &cntp))) @@ -487,7 +487,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec) ppid = proc_info->p_ppid; } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ppid; } @@ -507,7 +507,7 @@ std::vector child_pids(pid_type pid, boost::system::error_code & ec) std::unique_ptr kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)}; if (!kd) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } if ((proc_info = kvm_getproc2(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &cntp))) @@ -522,7 +522,7 @@ std::vector child_pids(pid_type pid, boost::system::error_code & ec) } } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } @@ -544,7 +544,7 @@ std::vector all_pids(boost::system::error_code & ec) std::unique_ptr kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)}; if (!kd) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &cntp))) @@ -559,7 +559,7 @@ std::vector all_pids(boost::system::error_code & ec) } } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } @@ -579,7 +579,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec) std::unique_ptr kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)}; if (!kd) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ppid; } if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &cntp))) @@ -587,7 +587,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec) ppid = proc_info->p_ppid; } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ppid; } @@ -607,7 +607,7 @@ std::vector child_pids(pid_type pid, boost::system::error_code & ec) std::unique_ptr kd{kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr)}; if (!kd) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } if ((proc_info = kvm_getprocs(kd.get(), KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &cntp))) @@ -622,7 +622,7 @@ std::vector child_pids(pid_type pid, boost::system::error_code & ec) } } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } @@ -645,7 +645,7 @@ std::vector all_pids(boost::system::error_code & ec) std::unique_ptr kd{kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr)}; if (!kd) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } while ((proc_info = kvm_nextproc(kd))) @@ -656,7 +656,7 @@ std::vector all_pids(boost::system::error_code & ec) } else { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) break; } } @@ -678,7 +678,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec) std::unique_ptr kd{kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr)}; if (!kd) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ppid; } if ((proc_info = kvm_getproc(kd, pid))) @@ -686,7 +686,7 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec) ppid = proc_info->p_ppid; } else - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ppid; } @@ -706,7 +706,7 @@ std::vector child_pids(pid_type pid, boost::system::error_code & ec) std::unique_ptr kd{kvm_open(nullptr, nullptr, nullptr, O_RDONLY, nullptr); if (!kd) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return vec; } while ((proc_info = kvm_nextproc(kd))) @@ -719,7 +719,7 @@ std::vector child_pids(pid_type pid, boost::system::error_code & ec) } else { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) break; } } diff --git a/include/boost/process/v2/impl/shell.ipp b/include/boost/process/v2/impl/shell.ipp index 12a9fa2c..da78404f 100644 --- a/include/boost/process/v2/impl/shell.ipp +++ b/include/boost/process/v2/impl/shell.ipp @@ -69,7 +69,11 @@ void shell::parse_() { argv_ = ::CommandLineToArgvW(input_.c_str(), &argc_); if (argv_ == nullptr) - detail::throw_last_error(); + { + error_code ec; + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec); + throw system_error(ec, "shell::parse"); + } } shell::~shell() diff --git a/include/boost/process/v2/posix/default_launcher.hpp b/include/boost/process/v2/posix/default_launcher.hpp index a2bb3b6c..f07d64fd 100644 --- a/include/boost/process/v2/posix/default_launcher.hpp +++ b/include/boost/process/v2/posix/default_launcher.hpp @@ -364,12 +364,12 @@ struct default_launcher pipe_guard pg; if (::pipe(pg.p)) { - ec.assign(errno, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category()) return basic_process{exec}; } if (::fcntl(pg.p[1], F_SETFD, FD_CLOEXEC)) { - ec.assign(errno, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category()) return basic_process{exec}; } ec = detail::on_setup(*this, executable, argv, inits ...); @@ -390,7 +390,7 @@ struct default_launcher detail::on_fork_error(*this, executable, argv, ec, inits...); detail::on_error(*this, executable, argv, ec, inits...); - ec.assign(errno, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category()) return basic_process{exec}; } else if (pid == 0) @@ -406,7 +406,7 @@ struct default_launcher ::execve(executable.c_str(), const_cast(argv), const_cast(env)); ignore_unused(::write(pg.p[1], &errno, sizeof(int))); - ec.assign(errno, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category()) detail::on_exec_error(*this, executable, argv, ec, inits...); ::exit(EXIT_FAILURE); return basic_process{exec}; @@ -422,12 +422,12 @@ struct default_launcher int err = errno; if ((err != EAGAIN) && (err != EINTR)) { - ec.assign(err, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, err, system_category()) break; } } if (count != 0) - ec.assign(child_error, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, child_error, system_category()) if (ec) { diff --git a/include/boost/process/v2/posix/fork_and_forget_launcher.hpp b/include/boost/process/v2/posix/fork_and_forget_launcher.hpp index 1b92b5d7..d97557f1 100644 --- a/include/boost/process/v2/posix/fork_and_forget_launcher.hpp +++ b/include/boost/process/v2/posix/fork_and_forget_launcher.hpp @@ -94,7 +94,7 @@ struct fork_and_forget_launcher : default_launcher detail::on_fork_error(*this, executable, argv, ec, inits...); detail::on_error(*this, executable, argv, ec, inits...); - ec.assign(errno, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category()) return basic_process{exec}; } else if (pid == 0) @@ -107,7 +107,7 @@ struct fork_and_forget_launcher : default_launcher if (!ec) ::execve(executable.c_str(), const_cast(argv), const_cast(env)); - ec.assign(errno, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category()) detail::on_exec_error(*this, executable, argv, ec, inits...); ::exit(EXIT_FAILURE); return basic_process{exec}; diff --git a/include/boost/process/v2/posix/pdfork_launcher.hpp b/include/boost/process/v2/posix/pdfork_launcher.hpp index 80f79c93..1f6d7ffc 100644 --- a/include/boost/process/v2/posix/pdfork_launcher.hpp +++ b/include/boost/process/v2/posix/pdfork_launcher.hpp @@ -85,12 +85,12 @@ struct pdfork_launcher : default_launcher pipe_guard pg; if (::pipe(pg.p)) { - ec.assign(errno, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category()) return basic_process{exec}; } if (::fcntl(pg.p[1], F_SETFD, FD_CLOEXEC)) { - ec.assign(errno, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category()) return basic_process{exec}; } ec = detail::on_setup(*this, executable, argv, inits ...); @@ -111,7 +111,7 @@ struct pdfork_launcher : default_launcher detail::on_fork_error(*this, executable, argv, ec, inits...); detail::on_error(*this, executable, argv, ec, inits...); - ec.assign(errno, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category()) return basic_process{exec}; } else if (pid == 0) @@ -128,7 +128,7 @@ struct pdfork_launcher : default_launcher ::execve(executable.c_str(), const_cast(argv), const_cast(env)); default_launcher::ignore_unused(::write(pg.p[1], &errno, sizeof(int))); - ec.assign(errno, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category()) detail::on_exec_error(*this, executable, argv, ec, inits...); ::exit(EXIT_FAILURE); return basic_process{exec}; @@ -143,12 +143,12 @@ struct pdfork_launcher : default_launcher int err = errno; if ((err != EAGAIN) && (err != EINTR)) { - ec.assign(err, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, err, system_category()) break; } } if (count != 0) - ec.assign(child_error, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, child_error, system_category()) if (ec) { diff --git a/include/boost/process/v2/posix/vfork_launcher.hpp b/include/boost/process/v2/posix/vfork_launcher.hpp index fde3842a..d156aad3 100644 --- a/include/boost/process/v2/posix/vfork_launcher.hpp +++ b/include/boost/process/v2/posix/vfork_launcher.hpp @@ -96,7 +96,7 @@ struct vfork_launcher : default_launcher detail::on_fork_error(*this, executable, argv, ec, inits...); detail::on_error(*this, executable, argv, ec, inits...); - ec.assign(errno, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category()) return basic_process{exec}; } else if (pid == 0) @@ -108,7 +108,7 @@ struct vfork_launcher : default_launcher if (!ec) ::execve(executable.c_str(), const_cast(argv), const_cast(env)); - ec.assign(errno, system_category()); + BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category()) detail::on_exec_error(*this, executable, argv, ec, inits...); ::exit(EXIT_FAILURE); return basic_process{exec}; diff --git a/include/boost/process/v2/stdio.hpp b/include/boost/process/v2/stdio.hpp index df373afc..f211fba2 100644 --- a/include/boost/process/v2/stdio.hpp +++ b/include/boost/process/v2/stdio.hpp @@ -69,7 +69,11 @@ struct process_io_binding { DWORD res; if (!::GetHandleInformation(h, &res)) - detail::throw_last_error("get_flags"); + { + error_code ec; + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec); + throw system_error(ec, "get_flags"); + } return res; } @@ -176,7 +180,7 @@ struct process_io_binding fd = p[1]; if (::fcntl(p[0], F_SETFD, FD_CLOEXEC) == -1) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ; } fd_needs_closing = true; @@ -195,7 +199,7 @@ struct process_io_binding fd = p[0]; if (::fcntl(p[1], F_SETFD, FD_CLOEXEC) == -1) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return ; } fd_needs_closing = true; diff --git a/include/boost/process/v2/windows/as_user_launcher.hpp b/include/boost/process/v2/windows/as_user_launcher.hpp index cf1c8b71..c1b1e30b 100644 --- a/include/boost/process/v2/windows/as_user_launcher.hpp +++ b/include/boost/process/v2/windows/as_user_launcher.hpp @@ -107,7 +107,7 @@ struct as_user_launcher : default_launcher if (ok == 0) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) detail::on_error(*this, executable, command_line, ec, inits...); if (process_information.hProcess != INVALID_HANDLE_VALUE) diff --git a/include/boost/process/v2/windows/default_launcher.hpp b/include/boost/process/v2/windows/default_launcher.hpp index 6b71202e..1ce0fe0e 100644 --- a/include/boost/process/v2/windows/default_launcher.hpp +++ b/include/boost/process/v2/windows/default_launcher.hpp @@ -314,7 +314,7 @@ struct default_launcher auto ec__ = detail::get_last_error(); if (ok == 0) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) detail::on_error(*this, executable, command_line, ec, inits...); if (process_information.hProcess != INVALID_HANDLE_VALUE) diff --git a/include/boost/process/v2/windows/with_logon_launcher.hpp b/include/boost/process/v2/windows/with_logon_launcher.hpp index c18a0263..df8e8228 100644 --- a/include/boost/process/v2/windows/with_logon_launcher.hpp +++ b/include/boost/process/v2/windows/with_logon_launcher.hpp @@ -111,7 +111,7 @@ struct with_logon_launcher : default_launcher if (ok == 0) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) detail::on_error(*this, executable, command_line, ec, inits...); if (process_information.hProcess != INVALID_HANDLE_VALUE) diff --git a/include/boost/process/v2/windows/with_token_launcher.hpp b/include/boost/process/v2/windows/with_token_launcher.hpp index c3e8383c..2775f777 100644 --- a/include/boost/process/v2/windows/with_token_launcher.hpp +++ b/include/boost/process/v2/windows/with_token_launcher.hpp @@ -106,7 +106,7 @@ struct with_token_launcher : default_launcher if (ok == 0) { - ec = detail::get_last_error(); + BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) detail::on_error(*this, executable, command_line, ec, inits...); if (process_information.hProcess != INVALID_HANDLE_VALUE) diff --git a/test/v2/pid.cpp b/test/v2/pid.cpp index aa77177f..532bfd48 100644 --- a/test/v2/pid.cpp +++ b/test/v2/pid.cpp @@ -19,7 +19,6 @@ 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()); @@ -39,6 +38,5 @@ 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 } From 4f9f4c398a041af207de8d3602c5c480f2804a1b Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Wed, 15 Feb 2023 02:04:24 +0800 Subject: [PATCH 19/27] close #296. --- .../boost/process/detail/posix/basic_cmd.hpp | 6 ++++-- test/cmd_test.cpp | 21 +++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/include/boost/process/detail/posix/basic_cmd.hpp b/include/boost/process/detail/posix/basic_cmd.hpp index d13d4c1b..c1f89976 100644 --- a/include/boost/process/detail/posix/basic_cmd.hpp +++ b/include/boost/process/detail/posix/basic_cmd.hpp @@ -155,13 +155,15 @@ private: std::vector exe_cmd_init::make_cmd() { + // any string must be writable. + static char empty_string[1] = ""; std::vector vec; if (!exe.empty()) - vec.push_back(&exe.front()); + vec.push_back(exe.empty() ? empty_string : &exe.front()); if (!args.empty()) { for (auto & v : args) - vec.push_back(&v.front()); + vec.push_back(v.empty() ? empty_string : &v.front()); } vec.push_back(nullptr); diff --git a/test/cmd_test.cpp b/test/cmd_test.cpp index 47ca034b..6586bd30 100644 --- a/test/cmd_test.cpp +++ b/test/cmd_test.cpp @@ -83,3 +83,24 @@ BOOST_AUTO_TEST_CASE(implicit) BOOST_TEST_MESSAGE(ec.message()); BOOST_CHECK_EQUAL(ret, 21); } + +BOOST_AUTO_TEST_CASE(empty_cmd) +{ + using boost::unit_test::framework::master_test_suite; + + std::error_code ec; + + fs::path pth = master_test_suite().argv[1]; + auto env = boost::this_process::environment(); + + auto itr = std::find_if(env.begin(), env.end(), + [](const bp::native_environment::entry_type & e){return boost::to_upper_copy(e.get_name()) == "PATH";}); + + BOOST_REQUIRE(itr != env.end()); + + (*itr) += fs::canonical(fs::absolute(pth.parent_path())).string(); + BOOST_REQUIRE(itr != env.end()); + + bp::system("sparring_partner \"\" ", ec); +} + From 0c1c6dfa9008170834babbc30085aa20069a70f2 Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Fri, 17 Feb 2023 11:34:15 +0800 Subject: [PATCH 20/27] sighchld service & test fixes. --- .../process/detail/posix/sigchld_service.hpp | 85 ++++++++++--------- test/async_pipe.cpp | 2 +- test/group_wait.cpp | 2 +- test/v2/ext.cpp | 2 +- 4 files changed, 47 insertions(+), 44 deletions(-) diff --git a/include/boost/process/detail/posix/sigchld_service.hpp b/include/boost/process/detail/posix/sigchld_service.hpp index 4eb6de6c..9d664093 100644 --- a/include/boost/process/detail/posix/sigchld_service.hpp +++ b/include/boost/process/detail/posix/sigchld_service.hpp @@ -7,8 +7,11 @@ #ifndef BOOST_PROCESS_DETAIL_POSIX_SIGCHLD_SERVICE_HPP_ #define BOOST_PROCESS_DETAIL_POSIX_SIGCHLD_SERVICE_HPP_ +#include #include #include +#include +#include #include #include #include @@ -26,6 +29,43 @@ class sigchld_service : public boost::asio::detail::service_base>> _receivers; inline void _handle_signal(const boost::system::error_code & ec); + + struct initiate_async_wait_op + { + sigchld_service * self; + template + void operator()(Initiation && init, ::pid_t pid) + { + // check if the child actually is running first + int status; + auto pid_res = ::waitpid(pid, &status, WNOHANG); + if (pid_res < 0) + { + auto ec = get_last_error(); + boost::asio::post( + self->_strand, + asio::append(std::forward(init), pid_res, ec)); + } + else if ((pid_res == pid) && (WIFEXITED(status) || WIFSIGNALED(status))) + boost::asio::post( + self->_strand, + boost::asio::append(std::forward(init), status, std::error_code{})); + else //still running + { + sigchld_service * self_ = self; + if (self->_receivers.empty()) + self->_signal_set.async_wait( + boost::asio::bind_executor( + self->_strand, + [self_](const boost::system::error_code &ec, int) + { + self_->_handle_signal(ec); + })); + self->_receivers.emplace_back(pid, init); + } + } + }; + public: sigchld_service(boost::asio::io_context & io_context) : boost::asio::detail::service_base(io_context) @@ -37,47 +77,10 @@ public: void (int, std::error_code)) async_wait(::pid_t pid, SignalHandler && handler) { - boost::asio::async_completion< - SignalHandler, void(boost::system::error_code)> init{handler}; - - auto & h = init.completion_handler; - boost::asio::dispatch( - _strand, - [this, pid, h] - { - //check if the child actually is running first - int status; - auto pid_res = ::waitpid(pid, &status, WNOHANG); - if (pid_res < 0) - { - auto ec = get_last_error(); - boost::asio::post( - _strand, - [pid_res, ec, h] - { - h(pid_res, ec); - }); - } - else if ((pid_res == pid) && (WIFEXITED(status) || WIFSIGNALED(status))) - boost::asio::post( - _strand, - [status, h] - { - h(status, {}); //successfully exited already - }); - else //still running - { - if (_receivers.empty()) - _signal_set.async_wait( - [this](const boost::system::error_code &ec, int) - { - boost::asio::dispatch(_strand, [this, ec]{this->_handle_signal(ec);}); - }); - _receivers.emplace_back(pid, h); - } - }); - - return init.result.get(); + return boost::asio::async_initiate< + SignalHandler, + void(int, std::error_code)>( + initiate_async_wait_op{this}, handler, pid); } void shutdown() override { diff --git a/test/async_pipe.cpp b/test/async_pipe.cpp index 0507dbd7..133c5417 100644 --- a/test/async_pipe.cpp +++ b/test/async_pipe.cpp @@ -72,7 +72,7 @@ BOOST_AUTO_TEST_CASE(multithreaded_async_pipe) asio::io_context ioc; std::vector threads; - for (int i = 0; i < std::thread::hardware_concurrency(); i++) + for (auto i = 0u; i < std::thread::hardware_concurrency(); i++) { threads.emplace_back([&ioc] { diff --git a/test/group_wait.cpp b/test/group_wait.cpp index aa0d9258..91c96b5b 100644 --- a/test/group_wait.cpp +++ b/test/group_wait.cpp @@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(wait_group_test, *boost::unit_test::timeout(5)) BOOST_CHECK_MESSAGE(!ec, ec.message()); BOOST_REQUIRE(c2.in_group(ec)); BOOST_CHECK_MESSAGE(!ec, ec.message()); - g.wait(); + g.wait(ec); BOOST_CHECK(!c1.running()); BOOST_CHECK(!c2.running()); diff --git a/test/v2/ext.cpp b/test/v2/ext.cpp index c82a09ff..7af93d45 100644 --- a/test/v2/ext.cpp +++ b/test/v2/ext.cpp @@ -80,7 +80,7 @@ BOOST_AUTO_TEST_CASE(cmd_exe) BOOST_CHECK_EQUAL(bp2::detail::conv_string(ref.data(), ref.size()), pth); BOOST_REQUIRE_EQUAL(cm.argc(), args.size() + 1); - for (auto i = 0; i < args.size(); i++) + for (auto i = 0u; i < args.size(); i++) { ref = cm.argv()[i + 1]; From 7a9ab79162dd477a9133c3b9b9e19b66e1b5f923 Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Mon, 20 Feb 2023 19:30:09 +0800 Subject: [PATCH 21/27] removed noexcept from env v2 --- include/boost/process/v2/environment.hpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/include/boost/process/v2/environment.hpp b/include/boost/process/v2/environment.hpp index 6309de88..72c4cfa7 100644 --- a/include/boost/process/v2/environment.hpp +++ b/include/boost/process/v2/environment.hpp @@ -488,7 +488,7 @@ struct key using string_type = std::basic_string; using string_view_type = basic_string_view; - key() noexcept = default; + key() {} key( const key& p ) = default; key( key&& p ) noexcept = default; key( const string_type& source ) : value_(source) {} @@ -524,7 +524,11 @@ struct key ~key() = default; key& operator=( const key& p ) = default; - key& operator=( key&& p ) noexcept(std::is_nothrow_move_constructible::value) = default; + key& operator=( key&& p ) + { + value_ = std::move(p.value_); + return *this; + } key& operator=( string_type&& source ) { value_ = std::move(source); @@ -708,7 +712,7 @@ struct value using string_type = std::basic_string; using string_view_type = basic_cstring_ref; - value() noexcept = default; + value() {} value( const value& p ) = default; value( const string_type& source ) : value_(source) {} @@ -742,7 +746,11 @@ struct value ~value() = default; value& operator=( const value& p ) = default; - value& operator=( value&& p ) noexcept(std::is_nothrow_move_constructible::value) = default; + value& operator=( value&& p ) + { + value_ = std::move(p.value_); + return *this; + } value& operator=( string_type&& source ) { value_ = std::move(source); @@ -935,7 +943,7 @@ struct key_value_pair using string_type = std::basic_string; using string_view_type = basic_cstring_ref; - key_value_pair() noexcept = default; + key_value_pair() {} key_value_pair( const key_value_pair& p ) = default; key_value_pair( key_value_pair&& p ) noexcept = default; key_value_pair(key_view key, value_view value) : value_(key.basic_string() + equality_sign + @@ -999,7 +1007,11 @@ struct key_value_pair ~key_value_pair() = default; key_value_pair& operator=( const key_value_pair& p ) = default; - key_value_pair& operator=( key_value_pair&& p ) noexcept(std::is_nothrow_move_constructible::value) = default; + key_value_pair& operator=( key_value_pair&& p ) + { + value_ = std::move(p.value_); + return *this; + } key_value_pair& operator=( string_type&& source ) { value_ = std::move(source); From e79c5f5edd1ae3be2632413883cae79fdad19f1b Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Tue, 21 Feb 2023 10:29:25 +0800 Subject: [PATCH 22/27] Updated pid test. --- test/v2/Jamfile.jam | 2 +- test/v2/pid.cpp | 42 ++++++++++++++++++++++++++---------------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/test/v2/Jamfile.jam b/test/v2/Jamfile.jam index 30262035..916e306c 100644 --- a/test/v2/Jamfile.jam +++ b/test/v2/Jamfile.jam @@ -59,11 +59,11 @@ test-suite standalone : [ run utf8.cpp test_impl ] [ run cstring_ref.cpp test_impl ] [ run environment.cpp test_impl ] - [ run pid.cpp test_impl : : : darwin:no ] [ run shell.cpp test_impl ] ; test-suite with_target : + [ run pid.cpp test_impl : --log_level=all --catch_system_errors=no -- : target ] [ run process.cpp test_impl : --log_level=all --catch_system_errors=no -- : target ] [ run windows.cpp test_impl : --log_level=all --catch_system_errors=no -- : target : no windows:yes windows:Advapi32 ] [ run ext.cpp test_impl : --log_level=all --catch_system_errors=no -- : target : darwin:no ] diff --git a/test/v2/pid.cpp b/test/v2/pid.cpp index 532bfd48..4102acec 100644 --- a/test/v2/pid.cpp +++ b/test/v2/pid.cpp @@ -5,10 +5,12 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include +#include #include #include +#include #include BOOST_AUTO_TEST_CASE(test_pid) @@ -22,21 +24,29 @@ BOOST_AUTO_TEST_CASE(test_pid) BOOST_CHECK_GT(all.size(), 0u); BOOST_CHECK(itr != all.end()); - std::vector children, grand_children; - auto grand_child_pids = [](bp2::pid_type pid, - std::vector & children, - std::vector & grand_children) - { - children = bp2::child_pids(pid); - for (unsigned i = 0; i < children.size(); i++) - { - std::vector tmp1; - std::vector tmp2 = bp2::child_pids(children[i]); - tmp1.insert(std::end(tmp1), std::begin(tmp2), std::end(tmp2)); - grand_children = tmp1; - } - return (!children.empty() || !grand_children.empty()); - }; - BOOST_CHECK_NE(grand_child_pids(bp2::root_pid, children, grand_children), false); + } + +BOOST_AUTO_TEST_CASE(child_pid) +{ + namespace bp2 = boost::process::v2; + + using boost::unit_test::framework::master_test_suite; + const auto pth = bp2::filesystem::absolute(master_test_suite().argv[1]); + + auto cs = bp2::child_pids(bp2::current_pid()); + boost::asio::io_context ctx; + bp2::process proc(ctx, pth, {"sleep", "50000"}); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + auto c2 = bp2::child_pids(bp2::current_pid()); + BOOST_CHECK_LT(cs.size(), c2.size()); + BOOST_CHECK(std::find(cs.begin(), cs.end(), proc.id()) == cs.end()); + BOOST_CHECK(std::find(c2.begin(), c2.end(), proc.id()) != c2.end()); + proc.terminate(); + proc.wait(); + + auto c3 = bp2::child_pids(bp2::current_pid()); + BOOST_CHECK(std::find(c3.begin(), c3.end(), proc.id()) == c3.end()); + BOOST_CHECK_LT(c3.size(), c2.size()); +} \ No newline at end of file From 2c6304b563e7220f48a54d93219ed823ba070a1b Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Tue, 21 Feb 2023 13:27:34 +0800 Subject: [PATCH 23/27] pid_test fixes for osx. --- include/boost/process/v2/impl/pid.ipp | 18 ++++++++---------- test/v2/pid.cpp | 1 + 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/include/boost/process/v2/impl/pid.ipp b/include/boost/process/v2/impl/pid.ipp index 61e848bb..e638fa14 100644 --- a/include/boost/process/v2/impl/pid.ipp +++ b/include/boost/process/v2/impl/pid.ipp @@ -147,15 +147,14 @@ std::vector child_pids(pid_type pid, boost::system::error_code & ec) std::vector all_pids(boost::system::error_code & ec) { std::vector vec; - vec.reserve(proc_listpids(PROC_ALL_PIDS, 0, nullptr, 0)); - if (proc_listpids(PROC_ALL_PIDS, 0, &vec[0], sizeof(pid_type) * vec.size())) + vec.resize(proc_listpids(PROC_ALL_PIDS, 0, nullptr, 0) / sizeof(pid_type)); + const auto sz = proc_listpids(PROC_ALL_PIDS, 0, &vec[0], sizeof(pid_type) * vec.size()); + if (sz < 0) { BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {}; } - auto itr = std::partition(vec.begin(), vec.end(), [](pid_type pt) {return pt != 0;}); - vec.erase(itr, vec.end()); - std::reverse(vec.begin(), vec.end()); + vec.resize(sz); return vec; } @@ -176,15 +175,14 @@ pid_type parent_pid(pid_type pid, boost::system::error_code & ec) 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, &vec[0], sizeof(pid_type) * vec.size())) + vec.resize(proc_listpids(PROC_PPID_ONLY, (uint32_t)pid, nullptr, 0) / sizeof(pid_type)); + const auto sz = proc_listpids(PROC_PPID_ONLY, (uint32_t)pid, &vec[0], sizeof(pid_type) * vec.size()); + if (sz < 0) { BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) return {}; } - auto itr = std::partition(vec.begin(), vec.end(), [](pid_type pt) {return pt != 0;}); - vec.erase(itr, vec.end()); - std::reverse(vec.begin(), vec.end()); + vec.resize(sz); return vec; } diff --git a/test/v2/pid.cpp b/test/v2/pid.cpp index 4102acec..570bc259 100644 --- a/test/v2/pid.cpp +++ b/test/v2/pid.cpp @@ -34,6 +34,7 @@ BOOST_AUTO_TEST_CASE(child_pid) using boost::unit_test::framework::master_test_suite; const auto pth = bp2::filesystem::absolute(master_test_suite().argv[1]); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); auto cs = bp2::child_pids(bp2::current_pid()); boost::asio::io_context ctx; From 09ba5e8d477370fc978db90a98c104de7d1c6e4f Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Wed, 22 Feb 2023 00:54:17 +0800 Subject: [PATCH 24/27] Reduced amount of test & fixed path comparisons. --- .drone.star | 2 +- .github/workflows/ci.yml | 125 --------------------------------------- test/v2/process.cpp | 9 +++ 3 files changed, 10 insertions(+), 126 deletions(-) diff --git a/.drone.star b/.drone.star index 03fb41f2..24fb934b 100644 --- a/.drone.star +++ b/.drone.star @@ -19,7 +19,7 @@ def main(ctx): linux_cxx("docs", "", packages="docbook docbook-xml docbook-xsl xsltproc libsaxonhe-java default-jre-headless flex libfl-dev bison unzip rsync", image="cppalliance/droneubuntu1804:1", buildtype="docs", buildscript="drone", environment={"COMMENT": "docs"}, globalenv=globalenv), linux_cxx("asan", "g++-8", packages="g++-8", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'COMMENT': 'asan', 'B2_VARIANT': 'debug', 'B2_TOOLSET': 'gcc-8', 'B2_CXXSTD': '11', 'B2_ASAN': '1', 'B2_DEFINES': 'BOOST_NO_STRESS_TEST=1', 'DRONE_EXTRA_PRIVILEGED': 'True', 'DRONE_JOB_UUID': '356a192b79'}, globalenv=globalenv, privileged=True), linux_cxx("ubsan", "g++-8", packages="g++-8", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'COMMENT': 'ubsan', 'B2_VARIANT': 'debug', 'B2_TOOLSET': 'gcc-8', 'B2_CXXSTD': '11', 'B2_UBSAN': '1', 'B2_DEFINES': 'BOOST_NO_STRESS_TEST=1', 'B2_LINKFLAGS': '-fuse-ld=gold', 'DRONE_JOB_UUID': '77de68daec'}, globalenv=globalenv), - linux_cxx("gcc 11 arm64", "g++-11", packages="g++-11", buildtype="boost", buildscript="drone", image="cppalliance/droneubuntu2004:multiarch", environment={ 'B2_TOOLSET': 'gcc-11', 'B2_CXXSTD': '11', 'DRONE_JOB_UUID': '17ba079169m'}, arch="arm64", globalenv=globalenv), + #linux_cxx("gcc 11 arm64", "g++-11", packages="g++-11", buildtype="boost", buildscript="drone", image="cppalliance/droneubuntu2004:multiarch", environment={ 'B2_TOOLSET': 'gcc-11', 'B2_CXXSTD': '11', 'DRONE_JOB_UUID': '17ba079169m'}, arch="arm64", globalenv=globalenv), linux_cxx("GCC 10, Debug + Coverage", "g++-10", packages="g++-10 libssl-dev libffi-dev binutils-gold gdb", image="cppalliance/droneubuntu2004:1", buildtype="boost", buildscript="drone", environment={"GCOV": "gcov-10", "LCOV_VERSION": "1.15", "VARIANT": "process_coverage", "TOOLSET": "gcc", "COMPILER": "g++-10", "CXXSTD": "11", "DRONE_BEFORE_INSTALL" : "process_coverage", "CODECOV_TOKEN": {"from_secret": "codecov_token"}}, globalenv=globalenv, privileged=True), # A set of jobs based on the earlier .travis.yml configuration: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0908e2e5..14776a89 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,10 +17,6 @@ jobs: fail-fast: false matrix: include: - - toolset: gcc-4.8 - cxxstd: "11" - os: ubuntu-18.04 - install: g++-4.8 - toolset: gcc-5 cxxstd: "11,14,1z" os: ubuntu-18.04 @@ -32,21 +28,10 @@ jobs: - toolset: gcc-7 cxxstd: "11,14,17" os: ubuntu-18.04 - - toolset: gcc-8 - cxxstd: "11,14,17,2a" - os: ubuntu-18.04 - install: g++-8 - - toolset: gcc-9 - cxxstd: "11,14,17,2a" - os: ubuntu-20.04 - toolset: gcc-10 cxxstd: "11,14,17,2a" os: ubuntu-20.04 install: g++-10 - - toolset: gcc-11 - cxxstd: "11,14,17,2a" - os: ubuntu-20.04 - install: g++-11 - toolset: gcc-12 cxxstd: "11,14,17,20,2b" os: ubuntu-22.04 @@ -262,114 +247,4 @@ jobs: cmake --build . ctest --output-on-failure --no-tests=error - posix-cmake-install: - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu-18.04 - - os: ubuntu-20.04 - - os: ubuntu-22.04 - - os: macos-11 - runs-on: ${{matrix.os}} - - steps: - - uses: actions/checkout@v2 - - - name: Install packages - if: matrix.install - run: sudo apt install ${{matrix.install}} - - - name: Setup Boost - run: | - echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY - LIBRARY=${GITHUB_REPOSITORY#*/} - echo LIBRARY: $LIBRARY - echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV - echo GITHUB_BASE_REF: $GITHUB_BASE_REF - echo GITHUB_REF: $GITHUB_REF - REF=${GITHUB_BASE_REF:-$GITHUB_REF} - REF=${REF#refs/heads/} - echo REF: $REF - BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true - echo BOOST_BRANCH: $BOOST_BRANCH - cd .. - git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root - cd boost-root - cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY - git submodule update --init tools/boostdep - python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY - - - name: Configure - run: | - cd ../boost-root - mkdir __build__ && cd __build__ - cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local .. - - - name: Install - run: | - cd ../boost-root/__build__ - cmake --build . --target install - - - name: Use the installed library - run: | - cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__ - cmake -DCMAKE_INSTALL_PREFIX=~/.local .. - cmake --build . - ctest --output-on-failure --no-tests=error - - posix-cmake-test: - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu-18.04 - - os: ubuntu-20.04 - - os: ubuntu-22.04 - - os: macos-11 - - runs-on: ${{matrix.os}} - - steps: - - uses: actions/checkout@v2 - - - name: Install packages - if: matrix.install - run: sudo apt install ${{matrix.install}} - - - name: Setup Boost - run: | - echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY - LIBRARY=${GITHUB_REPOSITORY#*/} - echo LIBRARY: $LIBRARY - echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV - echo GITHUB_BASE_REF: $GITHUB_BASE_REF - echo GITHUB_REF: $GITHUB_REF - REF=${GITHUB_BASE_REF:-$GITHUB_REF} - REF=${REF#refs/heads/} - echo REF: $REF - BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true - echo BOOST_BRANCH: $BOOST_BRANCH - cd .. - git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root - cd boost-root - cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY - git submodule update --init tools/boostdep - python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY - - - name: Configure - run: | - cd ../boost-root - mkdir __build__ && cd __build__ - cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON .. - - - name: Build tests - run: | - cd ../boost-root/__build__ - cmake --build . --target tests - - - name: Run tests - run: | - cd ../boost-root/__build__ - ctest --output-on-failure --no-tests=error diff --git a/test/v2/process.cpp b/test/v2/process.cpp index 5a98a9a1..e786bba8 100644 --- a/test/v2/process.cpp +++ b/test/v2/process.cpp @@ -424,6 +424,11 @@ BOOST_AUTO_TEST_CASE(print_other_cwd) BOOST_CHECK(sz != 0); BOOST_CHECK_MESSAGE((ec == asio::error::broken_pipe) || (ec == asio::error::eof), ec.message()); + + + if (out.back() != '/' && target.string().back() == '/') + out += '/'; + BOOST_CHECK_MESSAGE(bpv::filesystem::path(out) == target, bpv::filesystem::path(out) << " != " << target); @@ -553,6 +558,10 @@ BOOST_AUTO_TEST_CASE(bind_launcher) BOOST_CHECK(sz != 0); BOOST_CHECK_MESSAGE((ec == asio::error::broken_pipe) || (ec == asio::error::eof), ec.message()); + + if (out.back() != '/' && target.string().back() == '/') + out += '/'; + BOOST_CHECK_MESSAGE(bpv::filesystem::path(out) == target, bpv::filesystem::path(out) << " != " << target); From 1fbd8bb5e1820623b8db3dab51c54c1f4e231bdd Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Wed, 22 Feb 2023 12:26:31 +0800 Subject: [PATCH 25/27] handle_info include fix for handles.hpp. --- include/boost/process/detail/windows/handles.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/process/detail/windows/handles.hpp b/include/boost/process/detail/windows/handles.hpp index bf06ce76..a44ddb02 100644 --- a/include/boost/process/detail/windows/handles.hpp +++ b/include/boost/process/detail/windows/handles.hpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace boost { namespace process { namespace detail { From af2e884352cdfce4cb32033874766de9d7e004a0 Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Wed, 22 Feb 2023 13:01:46 +0800 Subject: [PATCH 26/27] Typo fixes. --- doc/concepts.qbk | 2 +- doc/posix_pseudocode.xml | 6 +++--- doc/v2/env.qbk | 2 +- doc/v2/introduction.qbk | 2 +- doc/v2/launcher.qbk | 12 ++++++------ doc/v2/quickstart.qbk | 6 +++--- doc/windows_pseudocode.xml | 2 +- example/v2/intro.cpp | 2 +- example/v2/intro_popen.cpp | 2 +- include/boost/process/async.hpp | 2 +- include/boost/process/async_system.hpp | 2 +- include/boost/process/detail/posix/basic_cmd.hpp | 4 ++-- include/boost/process/detail/posix/executor.hpp | 2 +- .../boost/process/detail/posix/io_context_ref.hpp | 2 +- include/boost/process/detail/posix/is_running.hpp | 2 +- include/boost/process/detail/windows/basic_cmd.hpp | 4 ++-- .../boost/process/detail/windows/child_handle.hpp | 2 +- include/boost/process/detail/windows/environment.hpp | 8 ++++---- include/boost/process/detail/windows/handles.hpp | 2 +- include/boost/process/env.hpp | 2 +- include/boost/process/extend.hpp | 2 +- include/boost/process/handles.hpp | 2 +- include/boost/process/posix.hpp | 2 +- include/boost/process/v2/detail/impl/utf8.ipp | 2 +- include/boost/process/v2/execute.hpp | 6 +++--- include/boost/process/v2/posix/bind_fd.hpp | 4 ++-- .../boost/process/v2/posix/detail/close_handles.ipp | 2 +- include/boost/process/v2/process.hpp | 2 +- include/boost/process/v2/shell.hpp | 4 ++-- include/boost/process/v2/stdio.hpp | 2 +- include/boost/process/v2/windows/creation_flags.hpp | 2 +- test/asio_no_deprecated.cpp | 4 ++-- test/async_pipe.cpp | 4 ++-- test/cmd_test.cpp | 2 +- 34 files changed, 54 insertions(+), 54 deletions(-) diff --git a/doc/concepts.qbk b/doc/concepts.qbk index ab7cb307..f9f27d49 100644 --- a/doc/concepts.qbk +++ b/doc/concepts.qbk @@ -41,7 +41,7 @@ which means, that the named pipe behaves like a file. Windows does provide a facility called [@https://msdn.microsoft.com/en-us/library/windows/desktop/aa365150(v=vs.85).aspx named pipes], which also have file-like names, but are in a different scope than the actual file system. -[note The main reason named pipes are part of this library, is because they need to be internally used for asynchrounous communication on windows.] +[note The main reason named pipes are part of this library, is because they need to be internally used for asynchronous communication on windows.] [endsect] diff --git a/doc/posix_pseudocode.xml b/doc/posix_pseudocode.xml index ef7348d8..5ba3d853 100644 --- a/doc/posix_pseudocode.xml +++ b/doc/posix_pseudocode.xml @@ -31,7 +31,7 @@ else if (pid == 0) //child process for (auto & s : seq) s.on_exec_error(*this); - unspecified();//here the error is send to the father process interally + unspecified();//here the error is sent to the father process internally std::exit(EXIT_FAILURE); return child(); //for C++ compliance @@ -39,7 +39,7 @@ else if (pid == 0) //child process child c(pid, exit_code); -unspecified();//here, we read the the error from the child process +unspecified();//here, we read the error from the child process if (error()) for (auto & s : seq) @@ -48,7 +48,7 @@ else for (auto & s : seq) s.on_success(*this); -//now we check again, because a on_success handler might've errored. +//now we check again, because an on_success handler might've errored. if (error()) { for (auto & s : seq) diff --git a/doc/v2/env.qbk b/doc/v2/env.qbk index 3f44dc2a..eb9bc993 100644 --- a/doc/v2/env.qbk +++ b/doc/v2/env.qbk @@ -9,7 +9,7 @@ Additionally, environment can be lists separated by `:` or `;`; `environment::va `environment::value_view` can be used to iterate those. Beyond that, the requirements on an environment are a low as possible; -an environment is either a list of strings or a list of string-pairs. It is however recommented to use the environment types, +an environment is either a list of strings or a list of string-pairs. It is however recommended to use the environment types, as to have the right value comparisons. To note is the `find_executable` functions, which searches in an environment for an executable. diff --git a/doc/v2/introduction.qbk b/doc/v2/introduction.qbk index 2554d3f8..e97f60b1 100644 --- a/doc/v2/introduction.qbk +++ b/doc/v2/introduction.qbk @@ -27,7 +27,7 @@ For process v2, the interfaces is simple: extern asio::io_context ctx; process proc(ctx, "./test", {"--help"}, process_io{nullptr, {}, {}}, process_environment(my_env)); -Every initializer adresses one logical compoent (e.g. stdio) instead of multiple ones accumulating. +Every initializer addresses one logical component (e.g. stdio) instead of multiple ones accumulating. Furthermore, every process has a path and arguments, instead of a confusing mixture of cmd-style and exe-args that can be randomly spread out. diff --git a/doc/v2/launcher.qbk b/doc/v2/launcher.qbk index 4e25728e..80d36870 100644 --- a/doc/v2/launcher.qbk +++ b/doc/v2/launcher.qbk @@ -21,7 +21,7 @@ A launcher is invoked through the call operator. ``` auto l = windows::as_user_launcher((HANDLE)0xDEADBEEF); asio::io_context ctx; - boost::system::eror_code ec; + boost::system::error_code ec; auto proc = l(ctx, ec, "C:\\User\\boost\\Downloads\\totally_not_a_virus.exe", {}); ``` @@ -38,7 +38,7 @@ Alternatively, the `vfork_launcher` can report errors directly back to the paren Thus some calls to the initializers occur after forking from the child process. ``` - struct custom_initalizer + struct custom_initializer { // functions called from the parent process: @@ -47,7 +47,7 @@ Thus some calls to the initializers occur after forking from the child process. template error_code on_setup(Launcher & launcher, const filesystem::path &executable, const char * const * (&cmd_line)); - // called for every initializer if an error occured during setup or process creation + // called for every initializer if an error occurred during setup or process creation template void on_error(Launcher & launcher, const filesystem::path &executable, const char * const * (&cmd_line), const error_code & ec); @@ -56,7 +56,7 @@ Thus some calls to the initializers occur after forking from the child process. template void on_success(Launcher & launcher, const filesystem::path &executable, const char * const * (&cmd_line)); - // called for every initializer if an error occured when forking, in addtion to on_error. + // called for every initializer if an error occurred when forking, in addition to on_error. template void on_fork_error(Launcher & launcher, const filesystem::path &executable, const char * const * (&cmd_line), const error_code & ec); @@ -94,7 +94,7 @@ The launcher will close all non-whitelisted file descriptors after `on_exec_setu [section:windows Windows Launchers] -Windows launchers are pretty streight forward, they will call the following functions on the initializer if present. +Windows launchers are pretty straight forward, they will call the following functions on the initializer if present. ``` struct custom_initializer @@ -103,7 +103,7 @@ Windows launchers are pretty streight forward, they will call the following func template error_code on_setup(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line); - // called for every initializer if an error occured during setup or process creation + // called for every initializer if an error occurred during setup or process creation template void on_error(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line, const error_code & ec); diff --git a/doc/v2/quickstart.qbk b/doc/v2/quickstart.qbk index 65b07fe8..4a770180 100644 --- a/doc/v2/quickstart.qbk +++ b/doc/v2/quickstart.qbk @@ -32,7 +32,7 @@ also returned from `.wait()`. ``` The normal exit-code is what the subprocess returned from `main`; -posix will however add addtional information about the process. +posix will however add additional information about the process. This is called the `native_exit_code`. @@ -42,7 +42,7 @@ The `.running()` function can be used to detect if the process is still active. [section:signal Signalling the subprocess] -The parent process can signal the subprocess demaning certain actions. +The parent process can signal the subprocess demanding certain actions. `.terminate` will cause the subprocess to exit immediately (`SIGKILL` on posix). This is the only reliable & portable way to end a subprocess. @@ -76,7 +76,7 @@ interpret as a signal to shutdown. [section:execute Execute functions] -Process v2 provides `execute` and `async_execute` functons that can be used for managed executions. +Process v2 provides `execute` and `async_execute` functions that can be used for managed executions. ``` assert(execute(process("/bin/ls", {}) == 0)); diff --git a/doc/windows_pseudocode.xml b/doc/windows_pseudocode.xml index 377da22e..fdcb780c 100644 --- a/doc/windows_pseudocode.xml +++ b/doc/windows_pseudocode.xml @@ -29,7 +29,7 @@ else for (auto & s : seq) s.on_success(*this); -//now we check again, because a on_success handler might've errored. +//now we check again, because an on_success handler might've errored. if (error()) { for (auto & s : seq) diff --git a/example/v2/intro.cpp b/example/v2/intro.cpp index 81579225..2e0f2363 100644 --- a/example/v2/intro.cpp +++ b/example/v2/intro.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2022Klemens Morgernstern +// Copyright (c) 2022 Klemens Morgenstern // // 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) diff --git a/example/v2/intro_popen.cpp b/example/v2/intro_popen.cpp index 47e94bb9..001f0bfb 100644 --- a/example/v2/intro_popen.cpp +++ b/example/v2/intro_popen.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2022Klemens Morgernstern +// Copyright (c) 2022Klemens Morgenstern // // 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) diff --git a/include/boost/process/async.hpp b/include/boost/process/async.hpp index 1fc03baf..e0d00222 100644 --- a/include/boost/process/async.hpp +++ b/include/boost/process/async.hpp @@ -5,7 +5,7 @@ /** \file boost/process/async.hpp -The header which provides the basic asynchrounous features. +The header which provides the basic asynchronous features. It provides the on_exit property, which allows callbacks when the process exits. It also implements the necessary traits for passing an boost::asio::io_context, which is needed for asynchronous communication. diff --git a/include/boost/process/async_system.hpp b/include/boost/process/async_system.hpp index f2d97ec4..c11acafe 100644 --- a/include/boost/process/async_system.hpp +++ b/include/boost/process/async_system.hpp @@ -11,7 +11,7 @@ /** * \file boost/process/async_system.hpp * - * Defines the asynchrounous version of the system function. + * Defines the asynchronous version of the system function. */ #ifndef BOOST_PROCESS_ASYNC_SYSTEM_HPP diff --git a/include/boost/process/detail/posix/basic_cmd.hpp b/include/boost/process/detail/posix/basic_cmd.hpp index c1f89976..d648e490 100644 --- a/include/boost/process/detail/posix/basic_cmd.hpp +++ b/include/boost/process/detail/posix/basic_cmd.hpp @@ -39,10 +39,10 @@ inline std::string build_cmd_shell(const std::string & exe, std::vector::invoke(boost::mpl::false_, boost::mpl::false_) } if (_ec) { - //if an error occured we need to reap the child process + //if an error occurred we need to reap the child process ::waitpid(this->pid, nullptr, WNOHANG); boost::fusion::for_each(seq, call_on_error(*this, _ec)); return child(); diff --git a/include/boost/process/detail/posix/io_context_ref.hpp b/include/boost/process/detail/posix/io_context_ref.hpp index 13afec3a..e9cddb62 100644 --- a/include/boost/process/detail/posix/io_context_ref.hpp +++ b/include/boost/process/detail/posix/io_context_ref.hpp @@ -80,7 +80,7 @@ struct io_context_ref : handler_base_ext void on_success(Executor& exec) { ios.notify_fork(boost::asio::io_context::fork_parent); - //must be on the heap so I can move it into the lambda. + //must be on the heap, so I can move it into the lambda. auto asyncs = boost::fusion::filter_if< is_async_handler< typename std::remove_reference< boost::mpl::_ > ::type diff --git a/include/boost/process/detail/posix/is_running.hpp b/include/boost/process/detail/posix/is_running.hpp index 3599e7f0..0f86b44d 100644 --- a/include/boost/process/detail/posix/is_running.hpp +++ b/include/boost/process/detail/posix/is_running.hpp @@ -34,7 +34,7 @@ inline bool is_running(const child_handle &p, int & exit_code, std::error_code & if (ret == -1) { - if (errno != ECHILD) //because it no child is running, than this one isn't either, obviously. + if (errno != ECHILD) //because it no child is running, then this one isn't either, obviously. ec = ::boost::process::detail::get_last_error(); return false; } diff --git a/include/boost/process/detail/windows/basic_cmd.hpp b/include/boost/process/detail/windows/basic_cmd.hpp index 760b28ba..656c89b7 100644 --- a/include/boost/process/detail/windows/basic_cmd.hpp +++ b/include/boost/process/detail/windows/basic_cmd.hpp @@ -62,7 +62,7 @@ inline std::string build_args(const std::string & exe, std::vector } } - if (!st.empty())//first one does not need a preceeding space + if (!st.empty())//first one does not need a preceding space st += ' '; st += arg; @@ -106,7 +106,7 @@ inline std::wstring build_args(const std::wstring & exe, std::vector::get(const pointer_type id) -> string_ if (size == sizeof(buf)) //the return size gives the size without the null, so I know this went wrong { - /*limit defined here https://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx - * but I used 32768 so it is a multiple of 4096. + /* limit defined here https://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx + * but I used 32768, so it is a multiple of 4096. */ constexpr static std::size_t max_size = 32768; //Handle variables longer then buf. @@ -232,7 +232,7 @@ basic_environment_impl::basic_environment_impl(const native_environment_im template inline auto basic_environment_impl::get(const string_type &id) -> string_type { - if (id.size() >= _data.size()) //ok, so it's impossible id is in there. + if (id.size() >= _data.size()) //ok, so it is impossible id is in there. return string_type(_data.data()); if (std::equal(id.begin(), id.end(), _data.begin()) && (_data[id.size()] == equal_sign())) @@ -273,7 +273,7 @@ template inline void basic_environment_impl::reset(const string_type &id) { //ok, we need to check the size of data first - if (id.size() >= _data.size()) //ok, so it's impossible id is in there. + if (id.size() >= _data.size()) //ok, so it is impossible id is in there. return; //check if it's the first one, spares us the search. diff --git a/include/boost/process/detail/windows/handles.hpp b/include/boost/process/detail/windows/handles.hpp index a44ddb02..901b339a 100644 --- a/include/boost/process/detail/windows/handles.hpp +++ b/include/boost/process/detail/windows/handles.hpp @@ -164,7 +164,7 @@ struct limit_handles_ : handler_base_ext } template - void on_sucess(Executor & exec) const + void on_success(Executor & exec) const { for (auto handle : handles_with_inherit_flag) ::boost::winapi::SetHandleInformation(handle, ::boost::winapi::HANDLE_FLAG_INHERIT_, ::boost::winapi::HANDLE_FLAG_INHERIT_); diff --git a/include/boost/process/env.hpp b/include/boost/process/env.hpp index 47258c28..1457a0dc 100644 --- a/include/boost/process/env.hpp +++ b/include/boost/process/env.hpp @@ -437,7 +437,7 @@ for both `id` and `value`. \subsubsection env_reset Reset variables -Reseting signle variables can be done in the following way: +Resetting single variables can be done in the following way: \code{.cpp} env[id] = boost::none; diff --git a/include/boost/process/extend.hpp b/include/boost/process/extend.hpp index fbbadc6a..39357360 100644 --- a/include/boost/process/extend.hpp +++ b/include/boost/process/extend.hpp @@ -70,7 +70,7 @@ using ::boost::process::detail::get_used_handles; ///This handler is invoked before the process in launched, to setup parameters. The required signature is `void(Exec &)`, where `Exec` is a template parameter. constexpr boost::process::detail::make_handler_t on_setup; -///This handler is invoked if an error occured. The required signature is `void(auto & exec, const std::error_code&)`, where `Exec` is a template parameter. +///This handler is invoked if an error occurred. The required signature is `void(auto & exec, const std::error_code&)`, where `Exec` is a template parameter. constexpr boost::process::detail::make_handler_t on_error; ///This handler is invoked if launching the process has succeeded. The required signature is `void(auto & exec)`, where `Exec` is a template parameter. constexpr boost::process::detail::make_handler_t on_success; diff --git a/include/boost/process/handles.hpp b/include/boost/process/handles.hpp index 23598f31..cc65940d 100644 --- a/include/boost/process/handles.hpp +++ b/include/boost/process/handles.hpp @@ -82,7 +82,7 @@ using limit_handles_ = ::boost::process::detail::api::limit_handles_; } /** - * The limit_handles property sets all properties to be inherited only expcitly. It closes all unused file-descriptors on posix after the fork and + * The limit_handles property sets all properties to be inherited only explicitly. It closes all unused file-descriptors on posix after the fork and * removes the inherit flags on windows. * * \note This is executed after the fork on posix. diff --git a/include/boost/process/posix.hpp b/include/boost/process/posix.hpp index 909837b8..4c3035eb 100644 --- a/include/boost/process/posix.hpp +++ b/include/boost/process/posix.hpp @@ -35,7 +35,7 @@ namespace boost { namespace boost { namespace process { -///Namespace containing the posix exensions. +///Namespace containing the posix extensions. namespace posix { /** This property lets you modify file-descriptors other than the standard ones (0,1,2). diff --git a/include/boost/process/v2/detail/impl/utf8.ipp b/include/boost/process/v2/detail/impl/utf8.ipp index 5a3c2091..c0e0bf69 100644 --- a/include/boost/process/v2/detail/impl/utf8.ipp +++ b/include/boost/process/v2/detail/impl/utf8.ipp @@ -128,7 +128,7 @@ inline int get_cont_octet_out_count_impl<4>(wchar_t word) { // Note that the following code will generate warnings on some platforms // where wchar_t is defined as UCS2. The warnings are superfluous as the - // specialization is never instantitiated with such compilers, but this + // specialization is never instantiated with such compilers, but this // can cause problems if warnings are being treated as errors, so we guard // against that. Including as we do // should be enough to get WCHAR_MAX defined. diff --git a/include/boost/process/v2/execute.hpp b/include/boost/process/v2/execute.hpp index 10a203a2..197e69d5 100644 --- a/include/boost/process/v2/execute.hpp +++ b/include/boost/process/v2/execute.hpp @@ -22,7 +22,7 @@ BOOST_PROCESS_V2_BEGIN_NAMESPACE * @tparam Executor The asio executor of the process handle * @param proc The process to be run. * @return int The exit code of the process - * @exception system_error An error that might have occured during the wait. + * @exception system_error An error that might have occurred during the wait. */ template inline int execute(basic_process proc) @@ -92,13 +92,13 @@ struct execute_op /** This function asynchronously for a process to complete. * * Cancelling the execution will signal the child process to exit - * with the following intepretations: + * with the following interpretations: * * - cancellation_type::total -> interrupt * - cancellation_type::partial -> request_exit * - cancellation_type::terminal -> terminate * - * It is to note that `async_execute` will us the lowest seelected cancellation + * It is to note that `async_execute` will us the lowest selected cancellation * type. A subprocess might ignore anything not terminal. */ template process_error_binding; * - `FILE*` any open file, including `stdin`, `stdout` and `stderr` * - a filesystem::path, which will open a readable or writable depending on the direction of the stream * - `native_handle` any native file handle (`HANDLE` on windows) or file descriptor (`int` on posix) - * - any io-object with a .native_handle() function that is comptaiblie with the above. E.g. a asio::ip::tcp::socket + * - any io-object with a .native_handle() function that is compatible with the above. E.g. a asio::ip::tcp::socket * - an asio::basic_writeable_pipe for stdin or asio::basic_readable_pipe for stderr/stdout. * * diff --git a/include/boost/process/v2/windows/creation_flags.hpp b/include/boost/process/v2/windows/creation_flags.hpp index 89f08d81..6e6f14be 100644 --- a/include/boost/process/v2/windows/creation_flags.hpp +++ b/include/boost/process/v2/windows/creation_flags.hpp @@ -36,7 +36,7 @@ struct process_creation_flags }; }; -/// A flag to create a new process group. Necessary to allow interupts for the subproces. +/// A flag to create a new process group. Necessary to allow interrupts for the subprocess. constexpr static process_creation_flags create_new_process_group; } diff --git a/test/asio_no_deprecated.cpp b/test/asio_no_deprecated.cpp index 45136c74..14541d53 100644 --- a/test/asio_no_deprecated.cpp +++ b/test/asio_no_deprecated.cpp @@ -1,6 +1,6 @@ // -// Created by kleme on 26.02.2018. -// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #define BOOST_ASIO_NO_DEPRECATED 1 #include diff --git a/test/async_pipe.cpp b/test/async_pipe.cpp index 133c5417..c616b0ec 100644 --- a/test/async_pipe.cpp +++ b/test/async_pipe.cpp @@ -122,7 +122,7 @@ BOOST_AUTO_TEST_CASE(move_pipe) } /* { - //copy an a closed pipe + //copy a closed pipe BOOST_TEST_CHECKPOINT("Copy assign"); BOOST_TEST_CHECKPOINT("Fourth move, from closed"); bp::async_pipe ap_inv{ios}; @@ -131,7 +131,7 @@ BOOST_AUTO_TEST_CASE(move_pipe) } { - //copy an a closed pipe + //copy a closed pipe BOOST_TEST_CHECKPOINT("Copy assign"); BOOST_TEST_CHECKPOINT("Fourth move, from closed"); bp::async_pipe ap_inv{ios}; diff --git a/test/cmd_test.cpp b/test/cmd_test.cpp index 6586bd30..79f29e21 100644 --- a/test/cmd_test.cpp +++ b/test/cmd_test.cpp @@ -30,7 +30,7 @@ namespace bp = boost::process; namespace fs = boost::process::filesystem; -BOOST_AUTO_TEST_CASE(excplicit) +BOOST_AUTO_TEST_CASE(explicit_) { using boost::unit_test::framework::master_test_suite; From 1fdd405a3f54772eac9c0093b367760f0033d41e Mon Sep 17 00:00:00 2001 From: Klemens Morgenstern Date: Wed, 22 Feb 2023 13:04:13 +0800 Subject: [PATCH 27/27] More typo fixes. --- doc/v2/quickstart.qbk | 2 +- doc/v2/stdio.qbk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/v2/quickstart.qbk b/doc/v2/quickstart.qbk index 4a770180..10e79360 100644 --- a/doc/v2/quickstart.qbk +++ b/doc/v2/quickstart.qbk @@ -90,7 +90,7 @@ The async version supports cancellation and will forward cancellation types as f ``` asio::io_context ctx; - asio::steady_timer timout{ctx, std::chrono::seconds(10)}; + asio::steady_timer timeout{ctx, std::chrono::seconds(10)}; asio::cancellation_signal sig; async_execute(process("/usr/bin/g++", {"hello_world.cpp"}), diff --git a/doc/v2/stdio.qbk b/doc/v2/stdio.qbk index 09a3b631..b21f6f71 100644 --- a/doc/v2/stdio.qbk +++ b/doc/v2/stdio.qbk @@ -23,7 +23,7 @@ automatically connected and the other side will get assigned to the child proces proc.wait(); ``` -readable pipes can be assigned to `out` an `err``, while writable_pipes can be assigned to `in`. +readable pipes can be assigned to `out` an `err`, while writable_pipes can be assigned to `in`. [endsect]