Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:10

0001 // Copyright (c) 2022 Klemens D. Morgenstern
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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     /// Rebinds the process_handle to another executor.
0053     template<typename Executor1>
0054     struct rebind_executor
0055     {
0056         /// The socket type when rebound to the specified executor.
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         //single value, not needed in the winapi.
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 //BOOST_PROCESS_V2_DETAIL_PROCESS_HANDLE_WINDOWS_HPP