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 11 #ifndef BOOST_PROCESS_DETAIL_ERROR_HPP 12 #define BOOST_PROCESS_DETAIL_ERROR_HPP 13 14 #include <boost/process/detail/config.hpp> 15 #include <boost/process/detail/traits.hpp> 16 17 18 #if defined(BOOST_POSIX_API) 19 #include <boost/process/detail/posix/handler.hpp> 20 #elif defined(BOOST_WINDOWS_API) 21 #include <boost/process/detail/windows/handler.hpp> 22 #endif 23 24 #include <system_error> 25 26 #include <type_traits> 27 #include <boost/fusion/algorithm/query/find_if.hpp> 28 #include <boost/fusion/sequence/intrinsic/begin.hpp> 29 #include <boost/fusion/sequence/intrinsic/end.hpp> 30 #include <boost/fusion/container/vector/convert.hpp> 31 #include <boost/fusion/iterator/deref.hpp> 32 #include <boost/fusion/sequence/comparison/equal_to.hpp> 33 #include <boost/fusion/container/set/convert.hpp> 34 #include <boost/type_index.hpp> 35 36 /** \file boost/process/error.hpp 37 * 38 * Header which provides the error properties. It allows to explicitly set the error handling, the properties are: 39 * 40 \xmlonly 41 <programlisting> 42 namespace boost { 43 namespace process { 44 <emphasis>unspecified</emphasis> <globalname alt="boost::process::ignore_error">ignore_error</globalname>; 45 <emphasis>unspecified</emphasis> <globalname alt="boost::process::throw_on_error">throw_on_error</globalname>; 46 <emphasis>unspecified</emphasis> <globalname alt="boost::process::error">error</globalname>; 47 <emphasis>unspecified</emphasis> <globalname alt="boost::process::error_ref">error_ref</globalname>; 48 <emphasis>unspecified</emphasis> <globalname alt="boost::process::error_code">error_code</globalname>; 49 } 50 } 51 </programlisting> 52 \endxmlonly 53 * For error there are two aliases: error_ref and error_code 54 */ 55 56 namespace boost { namespace process { 57 58 namespace detail { 59 60 struct throw_on_error_ : ::boost::process::detail::api::handler_base_ext 61 { 62 constexpr throw_on_error_() = default; 63 64 template <class Executor> on_errorboost::process::detail::throw_on_error_65 void on_error(Executor&, const std::error_code & ec) const 66 { 67 throw process_error(ec, "process creation failed"); 68 } 69 operator ()boost::process::detail::throw_on_error_70 const throw_on_error_ &operator()() const {return *this;} 71 }; 72 73 struct ignore_error_ : ::boost::process::detail::api::handler_base_ext 74 { 75 constexpr ignore_error_() = default; 76 }; 77 78 struct set_on_error : ::boost::process::detail::api::handler_base_ext 79 { 80 set_on_error(const set_on_error&) = default; set_on_errorboost::process::detail::set_on_error81 explicit set_on_error(std::error_code &ec) : ec_(ec) {} 82 83 template <class Executor> on_errorboost::process::detail::set_on_error84 void on_error(Executor&, const std::error_code & ec) const noexcept 85 { 86 ec_ = ec; 87 } 88 89 private: 90 std::error_code &ec_; 91 }; 92 93 struct error_ 94 { 95 constexpr error_() = default; operator ()boost::process::detail::error_96 set_on_error operator()(std::error_code &ec) const {return set_on_error(ec);} operator =boost::process::detail::error_97 set_on_error operator= (std::error_code &ec) const {return set_on_error(ec);} 98 99 }; 100 101 102 template<typename T> 103 struct is_error_handler : std::false_type {}; 104 105 template<> struct is_error_handler<set_on_error> : std::true_type {}; 106 template<> struct is_error_handler<throw_on_error_> : std::true_type {}; 107 template<> struct is_error_handler<ignore_error_> : std::true_type {}; 108 109 110 111 template<typename Iterator, typename End> 112 struct has_error_handler_impl 113 { 114 typedef typename boost::fusion::result_of::deref<Iterator>::type ref_type; 115 typedef typename std::remove_reference<ref_type>::type res_type_; 116 typedef typename std::remove_cv<res_type_>::type res_type; 117 typedef typename is_error_handler<res_type>::type cond; 118 119 typedef typename boost::fusion::result_of::next<Iterator>::type next_itr; 120 typedef typename has_error_handler_impl<next_itr, End>::type next; 121 122 typedef typename boost::mpl::or_<cond, next>::type type; 123 }; 124 125 template<typename Iterator> 126 struct has_error_handler_impl<Iterator, Iterator> 127 { 128 typedef boost::mpl::false_ type; 129 }; 130 131 132 template<typename Sequence> 133 struct has_error_handler 134 { 135 typedef typename boost::fusion::result_of::as_vector<Sequence>::type vector_type; 136 137 typedef typename has_error_handler_impl< 138 typename boost::fusion::result_of::begin<vector_type>::type, 139 typename boost::fusion::result_of::end< vector_type>::type 140 >::type type; 141 }; 142 143 template<typename Sequence> 144 struct has_ignore_error 145 { 146 typedef typename boost::fusion::result_of::as_set<Sequence>::type set_type; 147 typedef typename boost::fusion::result_of::has_key<set_type, ignore_error_>::type type1; 148 typedef typename boost::fusion::result_of::has_key<set_type, ignore_error_&>::type type2; 149 typedef typename boost::fusion::result_of::has_key<set_type, const ignore_error_&>::type type3; 150 typedef typename boost::mpl::or_<type1,type2, type3>::type type; 151 }; 152 153 struct error_builder 154 { 155 std::error_code *err; 156 typedef set_on_error result_type; get_initializerboost::process::detail::error_builder157 set_on_error get_initializer() {return set_on_error(*err);}; operator ()boost::process::detail::error_builder158 void operator()(std::error_code & ec) {err = &ec;}; 159 }; 160 161 template<> 162 struct initializer_tag<std::error_code> 163 { 164 typedef error_tag type; 165 }; 166 167 168 template<> 169 struct initializer_builder<error_tag> 170 { 171 typedef error_builder type; 172 }; 173 174 } 175 /**The ignore_error property will disable any error handling. This can be useful 176 on linux, where error handling will require a pipe.*/ 177 constexpr boost::process::detail::ignore_error_ ignore_error; 178 /**The throw_on_error property will enable the exception when launching a process. 179 It is unnecessary by default, but may be used, when an additional error_code is provided.*/ 180 constexpr boost::process::detail::throw_on_error_ throw_on_error; 181 /** 182 The error property will set the executor to handle any errors by setting an 183 [std::error_code](http://en.cppreference.com/w/cpp/error/error_code). 184 185 \code{.cpp} 186 std::error_code ec; 187 system("gcc", error(ec)); 188 \endcode 189 190 The following syntax is valid: 191 192 \code{.cpp} 193 error(ec); 194 error=ec; 195 \endcode 196 197 The overload version is achieved by just passing an object of 198 [std::error_code](http://en.cppreference.com/w/cpp/error/error_code) to the function. 199 200 201 */ 202 constexpr boost::process::detail::error_ error; 203 ///Alias for \xmlonly <globalname alt="boost::process::error">error</globalname> \endxmlonly . 204 constexpr boost::process::detail::error_ error_ref; 205 ///Alias for \xmlonly <globalname alt="boost::process::error">error</globalname> \endxmlonly . 206 constexpr boost::process::detail::error_ error_code; 207 208 209 }} 210 211 #endif 212