File indexing completed on 2025-01-18 09:50: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> && handle)
0088 : pid_(handle.pid_), handle_(std::move(handle.handle_))
0089 {
0090 }
0091
0092 basic_process_handle_win(basic_process_handle_win && handle)
0093 : pid_(handle.id()), handle_(std::move(handle.handle_))
0094 {
0095 handle.pid_ = static_cast<DWORD>(-1);
0096 }
0097
0098 basic_process_handle_win& operator=(basic_process_handle_win && handle)
0099 {
0100 pid_ = handle.pid_;
0101 handle_ = std::move(handle.handle_);
0102 handle.pid_ = static_cast<DWORD>(-1);
0103 return *this;
0104 }
0105
0106 ~basic_process_handle_win()
0107 {
0108 if (handle_.is_open())
0109 {
0110 error_code ec;
0111 handle_.close(ec);
0112 }
0113 }
0114
0115 native_handle_type native_handle()
0116 { return handle_.native_handle(); }
0117
0118 pid_type id() const
0119 { return pid_; }
0120
0121 void terminate_if_running(error_code &)
0122 {
0123 detail::terminate_if_running_(handle_.native_handle());
0124 }
0125
0126 void terminate_if_running()
0127 {
0128 detail::terminate_if_running_(handle_.native_handle());
0129 }
0130
0131 void wait(native_exit_code_type &exit_status, error_code &ec)
0132 {
0133 if (!detail::check_handle_(handle_.native_handle(), ec))
0134 return;
0135
0136 handle_.wait(ec);
0137 if (!ec)
0138 detail::get_exit_code_(handle_.native_handle(), exit_status, ec);
0139 }
0140
0141
0142 void wait(native_exit_code_type &exit_status)
0143 {
0144 error_code ec;
0145 wait(exit_status, ec);
0146 if (ec)
0147 detail::throw_error(ec, "wait(pid)");
0148 }
0149
0150 void interrupt(error_code &ec)
0151 {
0152 if (!detail::check_pid_(pid_, ec))
0153 return;
0154
0155 detail::interrupt_(pid_, ec);
0156 }
0157
0158 void interrupt()
0159 {
0160 error_code ec;
0161 interrupt(ec);
0162 if (ec)
0163 detail::throw_error(ec, "interrupt");
0164 }
0165
0166 void request_exit(error_code &ec)
0167 {
0168 if (!detail::check_pid_(pid_, ec))
0169 return;
0170 detail::request_exit_(pid_, ec);
0171 }
0172
0173 void request_exit()
0174 {
0175 error_code ec;
0176 request_exit(ec);
0177 if (ec)
0178 detail::throw_error(ec, "request_exit");
0179 }
0180
0181 void suspend(error_code &ec)
0182 {
0183 detail::suspend_(handle_.native_handle(), ec);
0184 }
0185
0186 void suspend()
0187 {
0188 error_code ec;
0189 suspend(ec);
0190 if (ec)
0191 detail::throw_error(ec, "suspend");
0192 }
0193
0194 void resume(error_code &ec)
0195 {
0196 detail::resume_(handle_.native_handle(), ec);
0197 }
0198
0199 void resume()
0200 {
0201 error_code ec;
0202 suspend(ec);
0203 if (ec)
0204 detail::throw_error(ec, "resume");
0205 }
0206
0207 void terminate(native_exit_code_type &exit_status, error_code &ec)
0208 {
0209 if (!detail::check_handle_(handle_.native_handle(), ec))
0210 return;
0211
0212 detail::terminate_(handle_.native_handle(), ec, exit_status);
0213 if (!ec)
0214 wait(exit_status, ec);
0215
0216 }
0217
0218 void terminate(native_exit_code_type &exit_status)
0219 {
0220 error_code ec;
0221 terminate(exit_status, ec);
0222 if (ec)
0223 detail::throw_error(ec, "terminate");
0224 }
0225
0226 bool running(native_exit_code_type &exit_code, error_code & ec)
0227 {
0228 if (!detail::check_handle_(handle_.native_handle(), ec))
0229 return false;
0230
0231 native_exit_code_type code;
0232
0233 detail::check_running_(handle_.native_handle(), ec, code);
0234 if (ec)
0235 return false;
0236
0237 if (process_is_running(code))
0238 return true;
0239 else
0240 {
0241 exit_code = code;
0242 return false;
0243 }
0244 }
0245
0246 bool running(native_exit_code_type &exit_code)
0247 {
0248 error_code ec;
0249 bool res = running(exit_code, ec);
0250 if (ec)
0251 detail::throw_error(ec, "is_running");
0252 return res;
0253 }
0254
0255 bool is_open() const
0256 {
0257 return handle_.is_open();
0258 }
0259
0260 template<BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(void(error_code, native_exit_code_type))
0261 WaitHandler BOOST_PROCESS_V2_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
0262 BOOST_PROCESS_V2_INITFN_AUTO_RESULT_TYPE(WaitHandler, void (error_code, native_exit_code_type))
0263 async_wait(WaitHandler &&handler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
0264 {
0265 return BOOST_PROCESS_V2_ASIO_NAMESPACE::async_compose<WaitHandler, void(error_code, native_exit_code_type)>(
0266 async_wait_op_{handle_}, handler, handle_
0267 );
0268 }
0269 template<typename>
0270 friend struct basic_process_handle_win;
0271 private:
0272 pid_type pid_;
0273 handle_type handle_;
0274
0275 struct async_wait_op_
0276 {
0277 handle_type &handle;
0278
0279 template<typename Self>
0280 void operator()(Self &&self)
0281 {
0282 handle.async_wait(std::move(self));
0283 }
0284
0285 template<typename Self>
0286 void operator()(Self &&self, error_code ec)
0287 {
0288 native_exit_code_type exit_code{};
0289 if (!ec)
0290 detail::get_exit_code_(handle.native_handle(), exit_code, ec);
0291 std::move(self).complete(ec, exit_code);
0292 }
0293 };
0294 };
0295
0296 #if !defined(BOOST_PROCESS_V2_HEADER_ONLY)
0297 extern template struct basic_process_handle_win<>;
0298 #endif
0299
0300 }
0301
0302 BOOST_PROCESS_V2_END_NAMESPACE
0303
0304
0305 #endif