error.hpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. // Copyright (c) 2006, 2007 Julio M. Merino Vidal
  2. // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
  3. // Copyright (c) 2009 Boris Schaeling
  4. // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
  5. // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
  6. // Copyright (c) 2016 Klemens D. Morgenstern
  7. //
  8. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  9. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_PROCESS_DETAIL_ERROR_HPP
  11. #define BOOST_PROCESS_DETAIL_ERROR_HPP
  12. #include <boost/process/detail/config.hpp>
  13. #include <boost/process/detail/traits.hpp>
  14. #if defined(BOOST_POSIX_API)
  15. #include <boost/process/detail/posix/handler.hpp>
  16. #elif defined(BOOST_WINDOWS_API)
  17. #include <boost/process/detail/windows/handler.hpp>
  18. #endif
  19. #include <system_error>
  20. #include <type_traits>
  21. #include <boost/fusion/algorithm/query/find_if.hpp>
  22. #include <boost/fusion/sequence/intrinsic/begin.hpp>
  23. #include <boost/fusion/sequence/intrinsic/end.hpp>
  24. #include <boost/fusion/container/vector/convert.hpp>
  25. #include <boost/fusion/iterator/deref.hpp>
  26. #include <boost/fusion/sequence/comparison/equal_to.hpp>
  27. #include <boost/fusion/container/set/convert.hpp>
  28. #include <boost/type_index.hpp>
  29. /** \file boost/process/error.hpp
  30. *
  31. * Header which provides the error properties. It allows to explicitly set the error handling, the properties are:
  32. *
  33. \xmlonly
  34. <programlisting>
  35. namespace boost {
  36. namespace process {
  37. <emphasis>unspecified</emphasis> <globalname alt="boost::process::ignore_error">ignore_error</globalname>;
  38. <emphasis>unspecified</emphasis> <globalname alt="boost::process::throw_on_error">throw_on_error</globalname>;
  39. <emphasis>unspecified</emphasis> <globalname alt="boost::process::error">error</globalname>;
  40. <emphasis>unspecified</emphasis> <globalname alt="boost::process::error_ref">error_ref</globalname>;
  41. <emphasis>unspecified</emphasis> <globalname alt="boost::process::error_code">error_code</globalname>;
  42. }
  43. }
  44. </programlisting>
  45. \endxmlonly
  46. * For error there are two aliases: error_ref and error_code
  47. */
  48. namespace boost { namespace process {
  49. namespace detail {
  50. struct throw_on_error_ : ::boost::process::detail::api::handler_base_ext
  51. {
  52. constexpr throw_on_error_() {};
  53. template <class Executor>
  54. void on_error(Executor&, const std::error_code & ec) const
  55. {
  56. throw process_error(ec, "process creation failed");
  57. }
  58. const throw_on_error_ &operator()() const {return *this;}
  59. };
  60. struct ignore_error_ : ::boost::process::detail::api::handler_base_ext
  61. {
  62. constexpr ignore_error_() {};
  63. };
  64. struct set_on_error : ::boost::process::detail::api::handler_base_ext
  65. {
  66. set_on_error(const set_on_error&) = default;
  67. explicit set_on_error(std::error_code &ec) : ec_(ec) {}
  68. template <class Executor>
  69. void on_error(Executor&, const std::error_code & ec) const
  70. {
  71. ec_ = ec;
  72. }
  73. private:
  74. std::error_code &ec_;
  75. };
  76. struct error_
  77. {
  78. constexpr error_() {}
  79. set_on_error operator()(std::error_code &ec) const {return set_on_error(ec);}
  80. set_on_error operator= (std::error_code &ec) const {return set_on_error(ec);}
  81. };
  82. template<typename T>
  83. struct is_error_handler : std::false_type {};
  84. template<> struct is_error_handler<set_on_error> : std::true_type {};
  85. template<> struct is_error_handler<throw_on_error_> : std::true_type {};
  86. template<> struct is_error_handler<ignore_error_> : std::true_type {};
  87. template<typename Iterator, typename End>
  88. struct has_error_handler_impl
  89. {
  90. typedef typename boost::fusion::result_of::deref<Iterator>::type ref_type;
  91. typedef typename std::remove_reference<ref_type>::type res_type_;
  92. typedef typename std::remove_cv<res_type_>::type res_type;
  93. typedef typename is_error_handler<res_type>::type cond;
  94. typedef typename boost::fusion::result_of::next<Iterator>::type next_itr;
  95. typedef typename has_error_handler_impl<next_itr, End>::type next;
  96. typedef typename boost::mpl::or_<cond, next>::type type;
  97. };
  98. template<typename Iterator>
  99. struct has_error_handler_impl<Iterator, Iterator>
  100. {
  101. typedef boost::mpl::false_ type;
  102. };
  103. template<typename Sequence>
  104. struct has_error_handler
  105. {
  106. typedef typename boost::fusion::result_of::as_vector<Sequence>::type vector_type;
  107. typedef typename has_error_handler_impl<
  108. typename boost::fusion::result_of::begin<vector_type>::type,
  109. typename boost::fusion::result_of::end< vector_type>::type
  110. >::type type;
  111. };
  112. template<typename Sequence>
  113. struct has_ignore_error
  114. {
  115. typedef typename boost::fusion::result_of::as_set<Sequence>::type set_type;
  116. typedef typename boost::fusion::result_of::has_key<set_type, ignore_error_>::type type1;
  117. typedef typename boost::fusion::result_of::has_key<set_type, ignore_error_&>::type type2;
  118. typedef typename boost::fusion::result_of::has_key<set_type, const ignore_error_&>::type type3;
  119. typedef typename boost::mpl::or_<type1,type2, type3>::type type;
  120. };
  121. struct error_builder
  122. {
  123. std::error_code *err;
  124. typedef set_on_error result_type;
  125. set_on_error get_initializer() {return set_on_error(*err);};
  126. void operator()(std::error_code & ec) {err = &ec;};
  127. };
  128. template<>
  129. struct initializer_tag<std::error_code>
  130. {
  131. typedef error_tag type;
  132. };
  133. template<>
  134. struct initializer_builder<error_tag>
  135. {
  136. typedef error_builder type;
  137. };
  138. }
  139. /**The ignore_error property will disable any error handling. This can be useful
  140. on linux, where error handling will require a pipe.*/
  141. constexpr boost::process::detail::ignore_error_ ignore_error;
  142. /**The throw_on_error property will enable the exception when launching a process.
  143. It is unnecessary by default, but may be used, when an additional error_code is provided.*/
  144. constexpr boost::process::detail::throw_on_error_ throw_on_error;
  145. /**
  146. The error property will set the executor to handle any errors by setting an
  147. [std::error_code](http://en.cppreference.com/w/cpp/error/error_code).
  148. \code{.cpp}
  149. std::error_code ec;
  150. system("gcc", error(ec));
  151. \endcode
  152. The following syntax is valid:
  153. \code{.cpp}
  154. error(ec);
  155. error=ec;
  156. \endcode
  157. The overload version is achieved by just passing an object of
  158. [std::error_code](http://en.cppreference.com/w/cpp/error/error_code) to the function.
  159. */
  160. constexpr boost::process::detail::error_ error;
  161. ///Alias for \xmlonly <globalname alt="boost::process::error">error</globalname> \endxmlonly .
  162. constexpr boost::process::detail::error_ error_ref;
  163. ///Alias for \xmlonly <globalname alt="boost::process::error">error</globalname> \endxmlonly .
  164. constexpr boost::process::detail::error_ error_code;
  165. }}
  166. #endif