File indexing completed on 2025-01-18 09:50:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef BOOST_PROCESS_CHILD_DECL_HPP
0018 #define BOOST_PROCESS_CHILD_DECL_HPP
0019
0020 #include <boost/process/detail/config.hpp>
0021 #include <chrono>
0022 #include <memory>
0023
0024 #include <boost/none.hpp>
0025 #include <atomic>
0026
0027 #if defined(BOOST_POSIX_API)
0028 #include <boost/process/detail/posix/child_handle.hpp>
0029 #include <boost/process/detail/posix/terminate.hpp>
0030 #include <boost/process/detail/posix/wait_for_exit.hpp>
0031 #include <boost/process/detail/posix/is_running.hpp>
0032 #elif defined(BOOST_WINDOWS_API)
0033 #include <boost/process/detail/windows/child_handle.hpp>
0034 #include <boost/process/detail/windows/terminate.hpp>
0035 #include <boost/process/detail/windows/wait_for_exit.hpp>
0036 #include <boost/process/detail/windows/is_running.hpp>
0037
0038 #endif
0039 namespace boost {
0040
0041 namespace process {
0042
0043 using ::boost::process::detail::api::pid_t;
0044
0045 class child
0046 {
0047 ::boost::process::detail::api::child_handle _child_handle;
0048 std::shared_ptr<std::atomic<int>> _exit_status = std::make_shared<std::atomic<int>>(::boost::process::detail::api::still_active);
0049 bool _attached = true;
0050 bool _terminated = false;
0051
0052 bool _exited()
0053 {
0054 return _terminated || !::boost::process::detail::api::is_running(_exit_status->load());
0055 };
0056 public:
0057 typedef ::boost::process::detail::api::child_handle child_handle;
0058 typedef child_handle::process_handle_t native_handle_t;
0059 explicit child(child_handle &&ch, std::shared_ptr<std::atomic<int>> &ptr) : _child_handle(std::move(ch)), _exit_status(ptr) {}
0060 explicit child(child_handle &&ch, const std::shared_ptr<std::atomic<int>> &ptr) : _child_handle(std::move(ch)), _exit_status(ptr) {}
0061 explicit child(child_handle &&ch) : _child_handle(std::move(ch)) {}
0062
0063 explicit child(pid_t pid) : _child_handle(pid), _attached(false) {};
0064 child(const child&) = delete;
0065 child(child && lhs) noexcept
0066 : _child_handle(std::move(lhs._child_handle)),
0067 _exit_status(std::move(lhs._exit_status)),
0068 _attached (lhs._attached),
0069 _terminated (lhs._terminated)
0070 {
0071 lhs._attached = false;
0072 }
0073
0074 template<typename ...Args>
0075 explicit child(Args&&...args);
0076 child() { }
0077 child& operator=(const child&) = delete;
0078 child& operator=(child && lhs)
0079 {
0080 _child_handle= std::move(lhs._child_handle);
0081 _exit_status = std::move(lhs._exit_status);
0082 _attached = lhs._attached;
0083 _terminated = lhs._terminated;
0084 lhs._attached = false;
0085 return *this;
0086 };
0087
0088 void detach() {_attached = false; }
0089 void join() {wait();}
0090 bool joinable() { return _attached;}
0091
0092 ~child()
0093 {
0094 std::error_code ec;
0095 if (_attached && !_exited() && running(ec))
0096 terminate(ec);
0097 }
0098 native_handle_t native_handle() const { return _child_handle.process_handle(); }
0099
0100
0101 int exit_code() const {return ::boost::process::detail::api::eval_exit_status(_exit_status->load());}
0102 pid_t id() const {return _child_handle.id(); }
0103
0104 int native_exit_code() const {return _exit_status->load();}
0105
0106 bool running()
0107 {
0108 std::error_code ec;
0109 bool b = running(ec);
0110 boost::process::detail::throw_error(ec, "running error");
0111 return b;
0112 }
0113
0114 void terminate()
0115 {
0116 std::error_code ec;
0117 terminate(ec);
0118 boost::process::detail::throw_error(ec, "terminate error");
0119 }
0120
0121 void wait()
0122 {
0123 std::error_code ec;
0124 wait(ec);
0125 boost::process::detail::throw_error(ec, "wait error");
0126 }
0127
0128 #if !defined(BOOST_PROCESS_NO_DEPRECATED)
0129
0130 template< class Rep, class Period >
0131 BOOST_DEPRECATED("wait_for is unreliable")
0132 bool wait_for (const std::chrono::duration<Rep, Period>& rel_time)
0133 {
0134 std::error_code ec;
0135 bool b = wait_for(rel_time, ec);
0136 boost::process::detail::throw_error(ec, "wait_for error");
0137 return b;
0138 }
0139
0140 template< class Clock, class Duration >
0141 BOOST_DEPRECATED("wait_until is unreliable")
0142 bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time )
0143 {
0144 std::error_code ec;
0145 bool b = wait_until(timeout_time, ec);
0146 boost::process::detail::throw_error(ec, "wait_until error");
0147 return b;
0148 }
0149 #endif
0150
0151 bool running(std::error_code & ec) noexcept
0152 {
0153 ec.clear();
0154 if (valid() && !_exited() && !ec)
0155 {
0156 int exit_code = 0;
0157 auto res = boost::process::detail::api::is_running(_child_handle, exit_code, ec);
0158 if (!ec && !res && !_exited())
0159 _exit_status->store(exit_code);
0160
0161 return res;
0162 }
0163 return false;
0164 }
0165
0166 void terminate(std::error_code & ec) noexcept
0167 {
0168 if (valid() && running(ec) && !ec)
0169 boost::process::detail::api::terminate(_child_handle, ec);
0170
0171 if (!ec)
0172 _terminated = true;
0173 }
0174
0175 void wait(std::error_code & ec) noexcept
0176 {
0177 if (!_exited() && valid())
0178 {
0179 int exit_code = 0;
0180 boost::process::detail::api::wait(_child_handle, exit_code, ec);
0181 if (!ec)
0182 _exit_status->store(exit_code);
0183 }
0184 }
0185
0186 #if !defined(BOOST_PROCESS_NO_DEPRECATED)
0187 template< class Rep, class Period >
0188 BOOST_DEPRECATED("wait_for is unreliable")
0189 bool wait_for (const std::chrono::duration<Rep, Period>& rel_time, std::error_code & ec) noexcept
0190 {
0191 return wait_until(std::chrono::steady_clock::now() + rel_time, ec);
0192 }
0193
0194 template< class Clock, class Duration >
0195 BOOST_DEPRECATED("wait_until is unreliable")
0196 bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time, std::error_code & ec) noexcept
0197 {
0198 if (!_exited())
0199 {
0200 int exit_code = 0;
0201 auto b = boost::process::detail::api::wait_until(_child_handle, exit_code, timeout_time, ec);
0202 if (!b || ec)
0203 return false;
0204 _exit_status->store(exit_code);
0205 }
0206 return true;
0207 }
0208 #endif
0209
0210 bool valid() const
0211 {
0212 return _child_handle.valid();
0213 }
0214 operator bool() const {return valid();}
0215
0216 bool in_group() const
0217 {
0218 return _child_handle.in_group();
0219 }
0220 bool in_group(std::error_code &ec) const noexcept
0221 {
0222 return _child_handle.in_group(ec);
0223 }
0224 };
0225
0226
0227
0228 }}
0229 #endif
0230