]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // Copyright (c) 2016 Klemens D. Morgenstern |
2 | // | |
3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | #ifndef BOOST_PROCESS_EXTENSIONS_HPP_ | |
7 | #define BOOST_PROCESS_EXTENSIONS_HPP_ | |
8 | ||
9 | #include <boost/process/detail/handler.hpp> | |
92f5a8d4 | 10 | #include <boost/process/detail/used_handles.hpp> |
1e59de90 | 11 | #include <memory> |
b32b8144 FG |
12 | |
13 | #if defined(BOOST_WINDOWS_API) | |
14 | #include <boost/process/detail/windows/executor.hpp> | |
15 | #include <boost/process/detail/windows/async_handler.hpp> | |
16 | #include <boost/process/detail/windows/asio_fwd.hpp> | |
17 | #else | |
18 | #include <boost/process/detail/posix/executor.hpp> | |
19 | #include <boost/process/detail/posix/async_handler.hpp> | |
20 | #include <boost/process/detail/posix/asio_fwd.hpp> | |
21 | #endif | |
22 | ||
23 | ||
24 | /** \file boost/process/extend.hpp | |
25 | * | |
26 | * This header which provides the types and functions provided for custom extensions. | |
27 | * | |
28 | * \xmlonly | |
29 | Please refer to the <link linkend="boost_process.extend">tutorial</link> for more details. | |
30 | \endxmlonly | |
31 | */ | |
32 | ||
33 | ||
34 | namespace boost { | |
35 | namespace process { | |
36 | namespace detail { | |
37 | template<typename Tuple> | |
38 | inline asio::io_context& get_io_context(const Tuple & tup); | |
39 | } | |
40 | ||
41 | ||
42 | ///Namespace for extensions \attention This is experimental. | |
43 | namespace extend { | |
44 | ||
45 | #if defined(BOOST_WINDOWS_API) | |
46 | ||
47 | template<typename Char, typename Sequence> | |
48 | using windows_executor = ::boost::process::detail::windows::executor<Char, Sequence>; | |
49 | template<typename Sequence> | |
50 | struct posix_executor; | |
51 | ||
52 | #elif defined(BOOST_POSIX_API) | |
53 | ||
54 | template<typename Sequence> | |
55 | using posix_executor = ::boost::process::detail::posix::executor<Sequence>; | |
56 | template<typename Char, typename Sequence> | |
57 | struct windows_executor; | |
58 | ||
59 | #endif | |
60 | ||
61 | using ::boost::process::detail::handler; | |
62 | using ::boost::process::detail::api::require_io_context; | |
63 | using ::boost::process::detail::api::async_handler; | |
64 | using ::boost::process::detail::get_io_context; | |
65 | using ::boost::process::detail::get_last_error; | |
66 | using ::boost::process::detail::throw_last_error; | |
92f5a8d4 TL |
67 | using ::boost::process::detail::uses_handles; |
68 | using ::boost::process::detail::foreach_used_handle; | |
69 | using ::boost::process::detail::get_used_handles; | |
b32b8144 FG |
70 | |
71 | ///This handler is invoked before the process in launched, to setup parameters. The required signature is `void(Exec &)`, where `Exec` is a template parameter. | |
72 | constexpr boost::process::detail::make_handler_t<boost::process::detail::on_setup_> on_setup; | |
73 | ///This handler is invoked if an error occured. The required signature is `void(auto & exec, const std::error_code&)`, where `Exec` is a template parameter. | |
74 | constexpr boost::process::detail::make_handler_t<boost::process::detail::on_error_> on_error; | |
75 | ///This handler is invoked if launching the process has succeeded. The required signature is `void(auto & exec)`, where `Exec` is a template parameter. | |
76 | constexpr boost::process::detail::make_handler_t<boost::process::detail::on_success_> on_success; | |
77 | ||
78 | #if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN) | |
79 | ///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. | |
80 | constexpr ::boost::process::detail::make_handler_t<::boost::process::detail::posix::on_fork_error_ > on_fork_error; | |
81 | ///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. | |
82 | constexpr ::boost::process::detail::make_handler_t<::boost::process::detail::posix::on_exec_setup_ > on_exec_setup; | |
83 | ///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. | |
84 | constexpr ::boost::process::detail::make_handler_t<::boost::process::detail::posix::on_exec_error_ > on_exec_error; | |
85 | #endif | |
86 | ||
87 | #if defined(BOOST_PROCESS_DOXYGEN) | |
88 | ///Helper function to get the last error code system-independent | |
89 | inline std::error_code get_last_error(); | |
90 | ||
91 | ///Helper function to get and throw the last system error. | |
92 | /// \throws boost::process::process_error | |
93 | /// \param msg A message to add to the error code. | |
94 | inline void throw_last_error(const std::string & msg); | |
95 | ///\overload void throw_last_error(const std::string & msg) | |
96 | inline void throw_last_error(); | |
97 | ||
98 | ||
99 | /** This function gets the io_context from the initializer sequence. | |
100 | * | |
101 | * \attention Yields a compile-time error if no `io_context` is provided. | |
102 | * \param seq The Sequence of the initializer. | |
103 | */ | |
104 | template<typename Sequence> | |
105 | inline asio::io_context& get_io_context(const Sequence & seq); | |
106 | ||
107 | /** This class is the base for every initializer, to be used for extensions. | |
108 | * | |
109 | * The usage is done through compile-time polymorphism, so that the required | |
110 | * functions can be overloaded. | |
111 | * | |
112 | * \note None of the function need to be `const`. | |
113 | * | |
114 | */ | |
115 | struct handler | |
116 | { | |
117 | ///This function is invoked before the process launch. \note It is not required to be const. | |
118 | template <class Executor> | |
119 | void on_setup(Executor&) const {} | |
120 | ||
121 | /** This function is invoked if an error occured while trying to launch the process. | |
122 | * \note It is not required to be const. | |
123 | */ | |
124 | template <class Executor> | |
125 | void on_error(Executor&, const std::error_code &) const {} | |
126 | ||
127 | /** This function is invoked if the process was successfully launched. | |
128 | * \note It is not required to be const. | |
129 | */ | |
130 | template <class Executor> | |
131 | void on_success(Executor&) const {} | |
132 | ||
133 | /**This function is invoked if an error occured during the call of `fork`. | |
134 | * \note This function will only be called on posix. | |
135 | */ | |
136 | template<typename Executor> | |
137 | void on_fork_error (Executor &, const std::error_code&) const {} | |
138 | ||
139 | /**This function is invoked if the call of `fork` was successful, before | |
140 | * calling `execve`. | |
141 | * \note This function will only be called on posix. | |
142 | * \attention It will be invoked from the new process. | |
143 | */ | |
144 | template<typename Executor> | |
145 | void on_exec_setup (Executor &) const {} | |
146 | ||
147 | /**This function is invoked if the call of `execve` failed. | |
148 | * \note This function will only be called on posix. | |
149 | * \attention It will be invoked from the new process. | |
150 | */ | |
151 | template<typename Executor> | |
152 | void on_exec_error (Executor &, const std::error_code&) const {} | |
153 | ||
154 | }; | |
155 | ||
156 | ||
157 | /** Inheriting the class will tell the launching process that an `io_context` is | |
158 | * needed. This should always be used when \ref get_io_context is used. | |
159 | * | |
160 | */ | |
161 | struct require_io_context {}; | |
162 | /** Inheriting this class will tell the launching function, that an event handler | |
163 | * shall be invoked when the process exits. This automatically does also inherit | |
164 | * \ref require_io_context. | |
165 | * | |
166 | * You must add the following function to your implementation: | |
167 | * | |
168 | \code{.cpp} | |
169 | template<typename Executor> | |
170 | std::function<void(int, const std::error_code&)> on_exit_handler(Executor & exec) | |
171 | { | |
92f5a8d4 TL |
172 | auto handler_ = this->handler; |
173 | return [handler_](int exit_code, const std::error_code & ec) | |
b32b8144 | 174 | { |
92f5a8d4 | 175 | handler_(static_cast<int>(exit_code), ec); |
b32b8144 FG |
176 | }; |
177 | ||
178 | } | |
179 | \endcode | |
180 | ||
181 | The callback will be obtained by calling this function on setup and it will be | |
182 | invoked when the process exits. | |
183 | ||
184 | * | |
185 | * \warning Cannot be used with \ref boost::process::spawn | |
186 | */ | |
187 | struct async_handler : handler, require_io_context | |
188 | { | |
189 | ||
190 | }; | |
191 | ||
192 | ///The posix executor type. | |
193 | /** This type represents the posix executor and can be used for overloading in a custom handler. | |
194 | * \note It is an alias for the implementation on posix, and a forward-declaration on windows. | |
195 | * | |
196 | * \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. | |
197 | ||
198 | ||
199 | \xmlonly | |
200 | As information for extension development, here is the structure of the process launching (in pseudo-code and uml) | |
201 | <xi:include href="posix_pseudocode.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> | |
202 | ||
203 | <mediaobject> | |
204 | <caption> | |
205 | <para>The sequence if when no error occurs.</para> | |
206 | </caption> | |
207 | <imageobject> | |
208 | <imagedata fileref="boost_process/posix_success.svg"/> | |
209 | </imageobject> | |
210 | </mediaobject> | |
211 | ||
212 | <mediaobject> | |
213 | <caption> | |
214 | <para>The sequence if the execution fails.</para> | |
215 | </caption> | |
216 | <imageobject> | |
217 | <imagedata fileref="boost_process/posix_exec_err.svg"/> | |
218 | </imageobject> | |
219 | </mediaobject> | |
220 | ||
221 | <mediaobject> | |
222 | <caption> | |
223 | <para>The sequence if the fork fails.</para> | |
224 | </caption> | |
225 | <imageobject> | |
226 | <imagedata fileref="boost_process/posix_fork_err.svg"/> | |
227 | </imageobject> | |
228 | </mediaobject> | |
229 | ||
230 | \endxmlonly | |
231 | ||
232 | ||
233 | \note Error handling if execve fails is done through a pipe, unless \ref ignore_error is used. | |
234 | ||
235 | */ | |
236 | template<typename Sequence> | |
237 | struct posix_executor | |
238 | { | |
239 | ///A reference to the actual initializer-sequence | |
240 | Sequence & seq; | |
241 | ///A pointer to the name of the executable. | |
242 | const char * exe = nullptr; | |
243 | ///A pointer to the argument-vector. | |
244 | char *const* cmd_line = nullptr; | |
245 | ///A pointer to the environment variables, as default it is set to [environ](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html) | |
246 | char **env = ::environ; | |
247 | ///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. */ | |
248 | pid_t pid = -1; | |
249 | ///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. | |
250 | std::shared_ptr<std::atomic<int>> exit_status = std::make_shared<std::atomic<int>>(still_active); | |
251 | ||
252 | ///This function returns a const reference to the error state of the executor. | |
253 | const std::error_code & error() const; | |
254 | ||
255 | ///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 | |
256 | /// might throw an exception. \note This is the required way to handle errors in initializers. | |
257 | void set_error(const std::error_code &ec, const std::string &msg); | |
258 | ///\overload void set_error(const std::error_code &ec, const std::string &msg); | |
259 | void set_error(const std::error_code &ec, const char* msg); | |
260 | }; | |
261 | ||
262 | ///The windows executor type. | |
263 | /** This type represents the posix executor and can be used for overloading in a custom handler. | |
264 | * | |
265 | * \note It is an alias for the implementation on posix, and a forward-declaration on windows. | |
266 | * \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. | |
267 | * \tparam Char The used char-type, either `char` or `wchar_t`. | |
268 | * | |
269 | ||
270 | \xmlonly | |
271 | 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"/> | |
272 | <mediaobject> | |
273 | <caption> | |
274 | <para>The sequence for windows process creation.</para> | |
275 | </caption> | |
276 | <imageobject> | |
277 | <imagedata fileref="boost_process/windows_exec.svg"/> | |
278 | </imageobject> | |
279 | </mediaobject> | |
280 | \endxmlonly | |
281 | ||
282 | */ | |
283 | ||
284 | template<typename Char, typename Sequence> | |
285 | struct windows_executor | |
286 | { | |
287 | ///A reference to the actual initializer-sequence | |
288 | Sequence & seq; | |
289 | ||
290 | ///A pointer to the name of the executable. It's null by default. | |
291 | const Char * exe = nullptr; | |
292 | ///A pointer to the argument-vector. Must be set by some initializer. | |
293 | char Char* cmd_line = nullptr; | |
294 | ///A pointer to the environment variables. It's null by default. | |
295 | char Char* env = nullptr; | |
296 | ///A pointer to the working directory. It's null by default. | |
297 | const Char * work_dir = nullptr; | |
298 | ||
299 | ///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. | |
300 | ::boost::detail::winapi::LPSECURITY_ATTRIBUTES_ proc_attrs = nullptr; | |
301 | ///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. | |
302 | ::boost::detail::winapi::LPSECURITY_ATTRIBUTES_ thread_attrs = nullptr; | |
303 | ///A logical bool value setting whether handles shall be inherited or not. | |
304 | ::boost::detail::winapi::BOOL_ inherit_handles = false; | |
305 | ||
306 | ///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) | |
307 | ::boost::detail::winapi::PROCESS_INFORMATION_ proc_info{nullptr, nullptr, 0,0}; | |
308 | ||
309 | ||
310 | ///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. | |
311 | std::shared_ptr<std::atomic<int>> exit_status = std::make_shared<std::atomic<int>>(still_active); | |
312 | ||
313 | ///This function returns a const reference to the error state of the executor. | |
314 | const std::error_code & error() const; | |
315 | ||
316 | ///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 | |
317 | /// might throw an exception. \note This is the required way to handle errors in initializers. | |
318 | void set_error(const std::error_code &ec, const std::string &msg); | |
319 | ///\overload void set_error(const std::error_code &ec, const std::string &msg); | |
320 | void set_error(const std::error_code &ec, const char* msg); | |
321 | ||
322 | ///The creation flags of the process | |
323 | ::boost::detail::winapi::DWORD_ creation_flags; | |
324 | ///The type of the [startup-info](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331.aspx), depending on the char-type. | |
325 | typedef typename detail::startup_info<Char>::type startup_info_t; | |
326 | ///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. | |
327 | typedef typename detail::startup_info_ex<Char>::type startup_info_ex_t; | |
328 | ///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. | |
329 | void set_startup_info_ex(); | |
330 | ///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. | |
331 | startup_info_t startup_info; | |
332 | ///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. | |
333 | startup_info_ex_t startup_info_ex; | |
334 | }; | |
335 | ||
336 | ||
337 | ||
338 | #endif | |
339 | ||
340 | } | |
341 | } | |
342 | } | |
343 | ||
344 | #endif |