File indexing completed on 2025-07-11 08:25:10
0001
0002
0003
0004
0005 #ifndef BOOST_PROCESS_V2_DETAIL_PROCESS_HANDLE_WINDOWS_HPP
0006 #define BOOST_PROCESS_V2_DETAIL_PROCESS_HANDLE_WINDOWS_HPP
0007
0008 #include <boost/process/v2/detail/config.hpp>
0009
0010 #include <boost/process/v2/exit_code.hpp>
0011 #include <boost/process/v2/pid.hpp>
0012 #include <boost/process/v2/detail/throw_error.hpp>
0013
0014 #if defined(BOOST_PROCESS_V2_STANDALONE)
0015 #include <asio/any_io_executor.hpp>
0016 #include <asio/compose.hpp>
0017 #include <asio/windows/basic_object_handle.hpp>
0018 #else
0019 #include <boost/asio/any_io_executor.hpp>
0020 #include <boost/asio/compose.hpp>
0021 #include <boost/asio/windows/basic_object_handle.hpp>
0022 #endif
0023
0024 BOOST_PROCESS_V2_BEGIN_NAMESPACE
0025
0026 namespace detail
0027 {
0028
0029 BOOST_PROCESS_V2_DECL void get_exit_code_( void * handle, native_exit_code_type & exit_code, error_code & ec);
0030 BOOST_PROCESS_V2_DECL void * open_process_(pid_type pid);
0031 BOOST_PROCESS_V2_DECL void terminate_if_running_(void * handle);
0032 BOOST_PROCESS_V2_DECL bool check_handle_(void* handle, error_code & ec);
0033 BOOST_PROCESS_V2_DECL bool check_pid_(pid_type pid_, error_code & ec);
0034 BOOST_PROCESS_V2_DECL void interrupt_(pid_type pid_, error_code & ec);
0035 BOOST_PROCESS_V2_DECL void suspend_(void * handle, error_code & ec);
0036 BOOST_PROCESS_V2_DECL void resume_(void * handle, error_code & ec);
0037 BOOST_PROCESS_V2_DECL void terminate_(void * handle, error_code & ec, native_exit_code_type & exit_code);
0038 BOOST_PROCESS_V2_DECL void request_exit_(pid_type pid_, error_code & ec);
0039 BOOST_PROCESS_V2_DECL void check_running_(void* handle, error_code & ec, native_exit_code_type & exit_status);
0040
0041 template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor>
0042 struct basic_process_handle_win
0043 {
0044 typedef BOOST_PROCESS_V2_ASIO_NAMESPACE::windows::basic_object_handle<Executor> handle_type;
0045 typedef typename handle_type::native_handle_type native_handle_type;
0046
0047 typedef Executor executor_type;
0048
0049 executor_type get_executor()
0050 { return handle_.get_executor(); }
0051
0052
0053 template<typename Executor1>
0054 struct rebind_executor
0055 {
0056
0057 typedef basic_process_handle_win<Executor1> other;
0058 };
0059
0060 template<typename ExecutionContext>
0061 basic_process_handle_win(ExecutionContext &context,
0062 typename std::enable_if<
0063 std::is_convertible<ExecutionContext &,
0064 BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context &>::value
0065 >::type = 0)
0066 : pid_(0), handle_(context)
0067 {
0068 }
0069
0070 basic_process_handle_win(Executor executor)
0071 : pid_(0), handle_(executor)
0072 {
0073 }
0074
0075 basic_process_handle_win(Executor executor, pid_type pid)
0076 : pid_(pid), handle_(executor, detail::open_process_(pid))
0077 {
0078 }
0079
0080 basic_process_handle_win(Executor executor, pid_type pid, native_handle_type process_handle)
0081 : pid_(pid), handle_(executor, process_handle)
0082 {
0083 }
0084
0085
0086 template<typename Executor1>
0087 basic_process_handle_win(basic_process_handle_win<Executor1> && other)
0088 : pid_(other.pid_), handle_(std::move(other.handle_))
0089 {
0090 other.pid_ = static_cast<DWORD>(-1);
0091 }
0092
0093 basic_process_handle_win(basic_process_handle_win && other)
0094 : pid_(other.pid_), handle_(std::move(other.handle_))
0095 {
0096 other.pid_ = static_cast<DWORD>(-1);
0097 }
0098
0099 basic_process_handle_win& operator=(basic_process_handle_win && other)
0100 {
0101 pid_ = other.pid_;
0102 handle_ = std::move(other.handle_);
0103 other.pid_ = static_cast<DWORD>(-1);
0104 return *this;
0105 }
0106
0107 template<typename Executor1>
0108 basic_process_handle_win& operator=(basic_process_handle_win<Executor1> && other)
0109 {
0110 pid_ = other.pid_;
0111 handle_ = std::move(other.handle_);
0112 other.pid_ = static_cast<DWORD>(-1);
0113 return *this;
0114 }
0115
0116 ~basic_process_handle_win()
0117 {
0118 if (handle_.is_open())
0119 {
0120 error_code ec;
0121 handle_.close(ec);
0122 }
0123 }
0124
0125 native_handle_type native_handle()
0126 { return handle_.native_handle(); }
0127
0128 pid_type id() const
0129 { return pid_; }
0130
0131 void terminate_if_running(error_code &)
0132 {
0133 detail::terminate_if_running_(handle_.native_handle());
0134 }
0135
0136 void terminate_if_running()
0137 {
0138 detail::terminate_if_running_(handle_.native_handle());
0139 }
0140
0141 void wait(native_exit_code_type &exit_status, error_code &ec)
0142 {
0143 if (!detail::check_handle_(handle_.native_handle(), ec))
0144 return;
0145
0146 handle_.wait(ec);
0147 if (!ec)
0148 detail::get_exit_code_(handle_.native_handle(), exit_status, ec);
0149 }
0150
0151
0152 void wait(native_exit_code_type &exit_status)
0153 {
0154 error_code ec;
0155 wait(exit_status, ec);
0156 if (ec)
0157 detail::throw_error(ec, "wait(pid)");
0158 }
0159
0160 void interrupt(error_code &ec)
0161 {
0162 if (!detail::check_pid_(pid_, ec))
0163 return;
0164
0165 detail::interrupt_(pid_, ec);
0166 }
0167
0168 void interrupt()
0169 {
0170 error_code ec;
0171 interrupt(ec);
0172 if (ec)
0173 detail::throw_error(ec, "interrupt");
0174 }
0175
0176 void request_exit(error_code &ec)
0177 {
0178 if (!detail::check_pid_(pid_, ec))
0179 return;
0180 detail::request_exit_(pid_, ec);
0181 }
0182
0183 void request_exit()
0184 {
0185 error_code ec;
0186 request_exit(ec);
0187 if (ec)
0188 detail::throw_error(ec, "request_exit");
0189 }
0190
0191 void suspend(error_code &ec)
0192 {
0193 detail::suspend_(handle_.native_handle(), ec);
0194 }
0195
0196 void suspend()
0197 {
0198 error_code ec;
0199 suspend(ec);
0200 if (ec)
0201 detail::throw_error(ec, "suspend");
0202 }
0203
0204 void resume(error_code &ec)
0205 {
0206 detail::resume_(handle_.native_handle(), ec);
0207 }
0208
0209 void resume()
0210 {
0211 error_code ec;
0212 resume(ec);
0213 if (ec)
0214 detail::throw_error(ec, "resume");
0215 }
0216
0217 void terminate(native_exit_code_type &exit_status, error_code &ec)
0218 {
0219 if (!detail::check_handle_(handle_.native_handle(), ec))
0220 return;
0221
0222 detail::terminate_(handle_.native_handle(), ec, exit_status);
0223 if (!ec)
0224 wait(exit_status, ec);
0225
0226 }
0227
0228 void terminate(native_exit_code_type &exit_status)
0229 {
0230 error_code ec;
0231 terminate(exit_status, ec);
0232 if (ec)
0233 detail::throw_error(ec, "terminate");
0234 }
0235
0236 bool running(native_exit_code_type &exit_code, error_code & ec)
0237 {
0238 if (!detail::check_handle_(handle_.native_handle(), ec))
0239 return false;
0240
0241 native_exit_code_type code;
0242
0243 detail::check_running_(handle_.native_handle(), ec, code);
0244 if (ec)
0245 return false;
0246
0247 if (process_is_running(code))
0248 return true;
0249 else
0250 exit_code = code;
0251
0252 return false;
0253 }
0254
0255 bool running(native_exit_code_type &exit_code)
0256 {
0257 error_code ec;
0258 bool res = running(exit_code, ec);
0259 if (ec)
0260 detail::throw_error(ec, "is_running");
0261 return res;
0262 }
0263
0264 bool is_open() const
0265 {
0266 return handle_.is_open();
0267 }
0268
0269 template<BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(void(error_code, native_exit_code_type))
0270 WaitHandler BOOST_PROCESS_V2_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
0271 BOOST_PROCESS_V2_INITFN_AUTO_RESULT_TYPE(WaitHandler, void (error_code, native_exit_code_type))
0272 async_wait(WaitHandler &&handler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
0273 {
0274 return BOOST_PROCESS_V2_ASIO_NAMESPACE::async_compose<WaitHandler, void(error_code, native_exit_code_type)>(
0275 async_wait_op_{handle_}, handler, handle_
0276 );
0277 }
0278 template<typename>
0279 friend struct basic_process_handle_win;
0280 private:
0281 pid_type pid_;
0282 handle_type handle_;
0283
0284 struct async_wait_op_
0285 {
0286 handle_type &handle;
0287
0288 template<typename Self>
0289 void operator()(Self &&self)
0290 {
0291 handle.async_wait(std::move(self));
0292 }
0293
0294 template<typename Self>
0295 void operator()(Self &&self, error_code ec)
0296 {
0297 native_exit_code_type exit_code{};
0298 if (!ec)
0299 detail::get_exit_code_(handle.native_handle(), exit_code, ec);
0300 std::move(self).complete(ec, exit_code);
0301 }
0302 };
0303 };
0304
0305 extern template struct basic_process_handle_win<>;
0306
0307 }
0308
0309 BOOST_PROCESS_V2_END_NAMESPACE
0310
0311
0312 #endif