Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-10 08:42:59

0001 // Copyright (c) 2016 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 
0006 #ifndef BOOST_PROCESS_EXTENSIONS_HPP_
0007 #define BOOST_PROCESS_EXTENSIONS_HPP_
0008 
0009 #include <boost/process/v1/detail/handler.hpp>
0010 #include <boost/process/v1/detail/used_handles.hpp>
0011 #include <memory>
0012 
0013 #if defined(BOOST_WINDOWS_API)
0014 #include <boost/process/v1/detail/windows/executor.hpp>
0015 #include <boost/process/v1/detail/windows/async_handler.hpp>
0016 #include <boost/process/v1/detail/windows/asio_fwd.hpp>
0017 #else
0018 #include <boost/process/v1/detail/posix/executor.hpp>
0019 #include <boost/process/v1/detail/posix/async_handler.hpp>
0020 #include <boost/process/v1/detail/posix/asio_fwd.hpp>
0021 #endif
0022 
0023 
0024 /** \file boost/process/extend.hpp
0025  *
0026  * This header which provides the types and functions provided for custom extensions.
0027  *
0028  * \xmlonly
0029    Please refer to the <link linkend="boost_process.extend">tutorial</link> for more details.
0030    \endxmlonly
0031  */
0032 
0033 
0034 namespace boost
0035 {
0036 namespace process
0037 {
0038 BOOST_PROCESS_V1_INLINE namespace v1
0039 {
0040 namespace detail
0041 {
0042 template<typename Tuple>
0043 inline asio::io_context &get_io_context(const Tuple &tup);
0044 }
0045 
0046 
0047 ///Namespace for extensions \attention This is experimental.
0048 namespace extend
0049 {
0050 
0051 #if defined(BOOST_WINDOWS_API)
0052 
0053 template<typename Char, typename Sequence>
0054 using windows_executor = ::boost::process::v1::detail::windows::executor<Char, Sequence>;
0055 template<typename Sequence>
0056 struct posix_executor;
0057 
0058 #elif defined(BOOST_POSIX_API)
0059 
0060 template<typename Sequence>
0061 using posix_executor = ::boost::process::v1::detail::posix::executor<Sequence>;
0062 template<typename Char, typename Sequence>
0063 struct windows_executor;
0064 
0065 #endif
0066 
0067 using ::boost::process::v1::detail::handler;
0068 using ::boost::process::v1::detail::api::require_io_context;
0069 using ::boost::process::v1::detail::api::async_handler;
0070 using ::boost::process::v1::detail::get_io_context;
0071 using ::boost::process::v1::detail::get_last_error;
0072 using ::boost::process::v1::detail::throw_last_error;
0073 using ::boost::process::v1::detail::uses_handles;
0074 using ::boost::process::v1::detail::foreach_used_handle;
0075 using ::boost::process::v1::detail::get_used_handles;
0076 
0077 ///This handler is invoked before the process in launched, to setup parameters. The required signature is `void(Exec &)`, where `Exec` is a template parameter.
0078 constexpr boost::process::v1::detail::make_handler_t<boost::process::v1::detail::on_setup_> on_setup;
0079 ///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.
0080 constexpr boost::process::v1::detail::make_handler_t<boost::process::v1::detail::on_error_> on_error;
0081 ///This handler is invoked if launching the process has succeeded. The required signature is `void(auto & exec)`, where `Exec` is a template parameter.
0082 constexpr boost::process::v1::detail::make_handler_t<boost::process::v1::detail::on_success_> on_success;
0083 
0084 #if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN)
0085 ///This handler is invoked if the fork failed. The required signature is `void(auto & exec)`, where `Exec` is a template parameter. \note Only available on posix.
0086 constexpr ::boost::process::v1::detail::make_handler_t<::boost::process::v1::detail::posix::on_fork_error_> on_fork_error;
0087 ///This handler is invoked if the fork succeeded. The required signature is `void(Exec &)`, where `Exec` is a template parameter. \note Only available on posix.
0088 constexpr ::boost::process::v1::detail::make_handler_t<::boost::process::v1::detail::posix::on_exec_setup_> on_exec_setup;
0089 ///This handler is invoked if the exec call errored. The required signature is `void(auto & exec)`, where `Exec` is a template parameter. \note Only available on posix.
0090 constexpr ::boost::process::v1::detail::make_handler_t<::boost::process::v1::detail::posix::on_exec_error_> on_exec_error;
0091 #endif
0092 
0093 #if defined(BOOST_PROCESS_DOXYGEN)
0094 ///Helper function to get the last error code system-independent
0095 inline std::error_code get_last_error();
0096 
0097 ///Helper function to get and throw the last system error.
0098 /// \throws boost::process::v1::process_error
0099 /// \param msg A message to add to the error code.
0100 inline void throw_last_error(const std::string & msg);
0101 ///\overload void throw_last_error(const std::string & msg)
0102 inline void throw_last_error();
0103 
0104 
0105 /** This function gets the io_context from the initializer sequence.
0106  *
0107  * \attention Yields a compile-time error if no `io_context` is provided.
0108  * \param seq The Sequence of the initializer.
0109  */
0110 template<typename Sequence>
0111 inline asio::io_context& get_io_context(const Sequence & seq);
0112 
0113 /** This class is the base for every initializer, to be used for extensions.
0114  *
0115  *  The usage is done through compile-time polymorphism, so that the required
0116  *  functions can be overloaded.
0117  *
0118  * \note None of the function need to be `const`.
0119  *
0120  */
0121 struct handler
0122 {
0123     ///This function is invoked before the process launch. \note It is not required to be const.
0124     template <class Executor>
0125     void on_setup(Executor&) const {}
0126 
0127     /** This function is invoked if an error occured while trying to launch the process.
0128      * \note It is not required to be const.
0129      */
0130     template <class Executor>
0131     void on_error(Executor&, const std::error_code &) const {}
0132 
0133     /** This function is invoked if the process was successfully launched.
0134      * \note It is not required to be const.
0135      */
0136     template <class Executor>
0137     void on_success(Executor&) const {}
0138 
0139     /**This function is invoked if an error occured during the call of `fork`.
0140      * \note This function will only be called on posix.
0141      */
0142     template<typename Executor>
0143     void on_fork_error  (Executor &, const std::error_code&) const {}
0144 
0145     /**This function is invoked if the call of `fork` was successful, before
0146      * calling `execve`.
0147      * \note This function will only be called on posix.
0148      * \attention It will be invoked from the new process.
0149      */
0150     template<typename Executor>
0151     void on_exec_setup  (Executor &) const {}
0152 
0153     /**This function is invoked if the call of `execve` failed.
0154      * \note This function will only be called on posix.
0155      * \attention It will be invoked from the new process.
0156      */
0157     template<typename Executor>
0158     void on_exec_error  (Executor &, const std::error_code&) const {}
0159 
0160 };
0161 
0162 
0163 /** Inheriting the class will tell the launching process that an `io_context` is
0164  * needed. This should always be used when \ref get_io_context is used.
0165  *
0166  */
0167 struct require_io_context {};
0168 /** Inheriting this class will tell the launching function, that an event handler
0169  * shall be invoked when the process exits. This automatically does also inherit
0170  * \ref require_io_context.
0171  *
0172  * You must add the following function to your implementation:
0173  *
0174  \code{.cpp}
0175 template<typename Executor>
0176 std::function<void(int, const std::error_code&)> on_exit_handler(Executor & exec)
0177 {
0178     auto handler_ = this->handler;
0179     return [handler_](int exit_code, const std::error_code & ec)
0180            {
0181                 handler_(static_cast<int>(exit_code), ec);
0182            };
0183 
0184 }
0185  \endcode
0186 
0187  The callback will be obtained by calling this function on setup and it will be
0188  invoked when the process exits.
0189 
0190  *
0191  * \warning Cannot be used with \ref boost::process::v1::spawn
0192  */
0193 struct async_handler : handler, require_io_context
0194 {
0195 
0196 };
0197 
0198 ///The posix executor type.
0199 /** This type represents the posix executor and can be used for overloading in a custom handler.
0200  * \note It is an alias for the implementation on posix, and a forward-declaration on windows.
0201  *
0202  * \tparam Sequence The used initializer-sequence, it is fulfills the boost.fusion [sequence](http://www.boost.org/doc/libs/master/libs/fusion/doc/html/fusion/sequence.html) concept.
0203 
0204 
0205 \xmlonly
0206 As information for extension development, here is the structure of the process launching (in pseudo-code and uml)
0207 <xi:include href="posix_pseudocode.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
0208 
0209 <mediaobject>
0210 <caption>
0211 <para>The sequence if when no error occurs.</para>
0212 </caption>
0213 <imageobject>
0214 <imagedata fileref="boost_process/posix_success.svg"/>
0215 </imageobject>
0216 </mediaobject>
0217 
0218 <mediaobject>
0219 <caption>
0220 <para>The sequence if the execution fails.</para>
0221 </caption>
0222 <imageobject>
0223 <imagedata fileref="boost_process/posix_exec_err.svg"/>
0224 </imageobject>
0225 </mediaobject>
0226 
0227 <mediaobject>
0228 <caption>
0229 <para>The sequence if the fork fails.</para>
0230 </caption>
0231 <imageobject>
0232 <imagedata fileref="boost_process/posix_fork_err.svg"/>
0233 </imageobject>
0234 </mediaobject>
0235 
0236 \endxmlonly
0237 
0238 
0239 \note Error handling if execve fails is done through a pipe, unless \ref ignore_error is used.
0240 
0241  */
0242 template<typename Sequence>
0243 struct posix_executor
0244 {
0245     ///A reference to the actual initializer-sequence
0246      Sequence & seq;
0247     ///A pointer to the name of the executable.
0248      const char * exe      = nullptr;
0249      ///A pointer to the argument-vector.
0250      char *const* cmd_line = nullptr;
0251      ///A pointer to the environment variables, as default it is set to [environ](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html)
0252      char **env      = ::environ;
0253      ///The pid of the process - it will be -1 before invoking [fork](http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html), and after forking either 0 for the new process or a positive value if in the current process. */
0254      pid_t pid = -1;
0255      ///This shared-pointer holds the exit code. It's done this way, so it can be shared between an `asio::io_context` and \ref child.
0256      std::shared_ptr<std::atomic<int>> exit_status = std::make_shared<std::atomic<int>>(still_active);
0257 
0258      ///This function returns a const reference to the error state of the executor.
0259      const std::error_code & error() const;
0260 
0261      ///This function can be used to report an error to the executor. This will be handled according to the configuration of the executor, i.e. it
0262      /// might throw an exception. \note This is the required way to handle errors in initializers.
0263      void set_error(const std::error_code &ec, const std::string &msg);
0264      ///\overload void set_error(const std::error_code &ec, const std::string &msg);
0265      void set_error(const std::error_code &ec, const char* msg);
0266 };
0267 
0268 ///The windows executor type.
0269 /** This type represents the posix executor and can be used for overloading in a custom handler.
0270  *
0271  * \note It is an alias for the implementation on posix, and a forward-declaration on windows.
0272  * \tparam Sequence The used initializer-sequence, it is fulfills the boost.fusion [sequence](http://www.boost.org/doc/libs/master/libs/fusion/doc/html/fusion/sequence.html) concept.
0273  * \tparam Char The used char-type, either `char` or `wchar_t`.
0274  *
0275 
0276 \xmlonly
0277 As information for extension development, here is the structure of the process launching (in pseudo-code and uml)<xi:include href="windows_pseudocode.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
0278 <mediaobject>
0279 <caption>
0280 <para>The sequence for windows process creation.</para>
0281 </caption>
0282 <imageobject>
0283 <imagedata fileref="boost_process/windows_exec.svg"/>
0284 </imageobject>
0285 </mediaobject>
0286 \endxmlonly
0287 
0288  */
0289 
0290 template<typename Char, typename Sequence>
0291 struct windows_executor
0292 {
0293     ///A reference to the actual initializer-sequence
0294      Sequence & seq;
0295 
0296      ///A pointer to the name of the executable. It's null by default.
0297      const Char * exe      = nullptr;
0298      ///A pointer to the argument-vector. Must be set by some initializer.
0299      char  Char* cmd_line = nullptr;
0300      ///A pointer to the environment variables. It's null by default.
0301      char  Char* env      = nullptr;
0302      ///A pointer to the working directory. It's null by default.
0303      const Char * work_dir = nullptr;
0304 
0305      ///A pointer to the process-attributes of type [SECURITY_ATTRIBUTES](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379560.aspx). It's null by default.
0306      ::boost::detail::winapi::LPSECURITY_ATTRIBUTES_ proc_attrs   = nullptr;
0307      ///A pointer to the thread-attributes of type [SECURITY_ATTRIBUTES](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379560.aspx). It' null by default.
0308      ::boost::detail::winapi::LPSECURITY_ATTRIBUTES_ thread_attrs = nullptr;
0309      ///A logical bool value setting whether handles shall be inherited or not.
0310      ::boost::detail::winapi::BOOL_ inherit_handles = false;
0311 
0312      ///The element holding the process-information after process creation. The type is [PROCESS_INFORMATION](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684873.aspx)
0313      ::boost::detail::winapi::PROCESS_INFORMATION_ proc_info{nullptr, nullptr, 0,0};
0314 
0315 
0316      ///This shared-pointer holds the exit code. It's done this way, so it can be shared between an `asio::io_context` and \ref child.
0317      std::shared_ptr<std::atomic<int>> exit_status = std::make_shared<std::atomic<int>>(still_active);
0318 
0319      ///This function returns a const reference to the error state of the executor.
0320      const std::error_code & error() const;
0321 
0322      ///This function can be used to report an error to the executor. This will be handled according to the configuration of the executor, i.e. it
0323      /// might throw an exception. \note This is the required way to handle errors in initializers.
0324      void set_error(const std::error_code &ec, const std::string &msg);
0325      ///\overload void set_error(const std::error_code &ec, const std::string &msg);
0326      void set_error(const std::error_code &ec, const char* msg);
0327 
0328      ///The creation flags of the process
0329     ::boost::detail::winapi::DWORD_ creation_flags;
0330     ///The type of the [startup-info](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331.aspx), depending on the char-type.
0331     typedef typename detail::startup_info<Char>::type    startup_info_t;
0332     ///The type of the [extended startup-info](https://msdn.microsoft.com/de-de/library/windows/desktop/ms686329.aspx), depending the char-type; only defined with winapi-version equal or higher than 6.
0333     typedef typename detail::startup_info_ex<Char>::type startup_info_ex_t;
0334     ///This function switches the information, so that the extended structure is used. \note It's only defined with winapi-version equal or higher than 6.
0335     void set_startup_info_ex();
0336     ///This element is an instance or a reference (if \ref startup_info_ex exists) to the [startup-info](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331.aspx) for the process.
0337     startup_info_t startup_info;
0338     ///This element is the instance of the  [extended startup-info](https://msdn.microsoft.com/de-de/library/windows/desktop/ms686329.aspx). It is only available with a winapi-version equal or highter than 6.
0339     startup_info_ex_t  startup_info_ex;
0340 };
0341 
0342 
0343 
0344 #endif
0345 
0346 }
0347 }
0348 }
0349 }
0350 #endif