1 #pragma once 2 3 #include <systemd/sd-bus.h> 4 5 #include <nlohmann/json_fwd.hpp> 6 #include <sdbusplus/sdbus.hpp> 7 #include <sdbusplus/utility/consteval_string.hpp> 8 9 #include <exception> 10 #include <string> 11 12 namespace sdbusplus 13 { 14 15 enum class UnpackErrorReason 16 { 17 missingProperty, 18 wrongType 19 }; 20 21 namespace exception 22 { 23 24 /** Base exception class for all sdbusplus exceptions, including those created 25 * by the bindings. */ 26 struct exception : public std::exception 27 { 28 virtual const char* name() const noexcept = 0; 29 virtual const char* description() const noexcept = 0; 30 virtual int get_errno() const noexcept = 0; 31 32 virtual int set_error(sd_bus_error*) const; 33 virtual int set_error(SdBusInterface*, sd_bus_error*) const; 34 35 private: 36 // This unused function is to ensure that the vtable for this class is 37 // properly emitted when `-flto=auto` is used, which is the default in 38 // Yocto builds. Without this, the vtable is a hidden symbol and no 39 // users can inherit from our exception type directly. 40 virtual void unused() const noexcept; 41 }; 42 43 /** base exception class for all errors created by the sdbus++ generator */ 44 struct generated_exception : public exception 45 { 46 int get_errno() const noexcept override; 47 }; 48 49 /** Non-templated base for all new errors and events created by the sdbus++ 50 * generator */ 51 struct generated_event_base : public generated_exception 52 { 53 virtual auto to_json() const -> nlohmann::json = 0; 54 virtual int severity() const noexcept = 0; 55 }; 56 57 /** base exception for all new errors and events created by the sdbus++ 58 * generator */ 59 template <typename Event> 60 struct generated_event : public generated_event_base 61 { namesdbusplus::exception::generated_event62 const char* name() const noexcept override 63 { 64 return Event::errName; 65 } 66 descriptionsdbusplus::exception::generated_event67 const char* description() const noexcept override 68 { 69 return Event::errDesc; 70 } 71 whatsdbusplus::exception::generated_event72 const char* what() const noexcept override 73 { 74 return Event::errWhat; 75 } 76 get_errnosdbusplus::exception::generated_event77 int get_errno() const noexcept override 78 { 79 return Event::errErrno; 80 } 81 severitysdbusplus::exception::generated_event82 int severity() const noexcept override 83 { 84 return Event::errSeverity; 85 } 86 87 template <utility::details::consteval_string_holder V> 88 using metadata_t = utility::consteval_string<V>; 89 90 protected: 91 mutable std::string jsonString; 92 }; 93 94 /** base exception class for all errors generated by sdbusplus itself. */ 95 struct internal_exception : public exception 96 {}; 97 98 /** Exception for when an underlying sd_bus method call fails. */ 99 class SdBusError final : public internal_exception 100 { 101 public: 102 /** Errno must be positive */ 103 SdBusError(int error, const char* prefix, 104 SdBusInterface* intf = &sdbus_impl); 105 SdBusError(int error, std::string&& prefix, 106 SdBusInterface* intf = &sdbus_impl); 107 /** Becomes the owner of the error */ 108 SdBusError(sd_bus_error* error, const char* prefix, 109 SdBusInterface* intf = &sdbus_impl); 110 111 SdBusError(const SdBusError&) = delete; 112 SdBusError& operator=(const SdBusError&) = delete; 113 SdBusError(SdBusError&& other); 114 SdBusError& operator=(SdBusError&& other); 115 ~SdBusError() override; 116 117 const char* name() const noexcept override; 118 const char* description() const noexcept override; 119 const char* what() const noexcept override; 120 int get_errno() const noexcept override; 121 const sd_bus_error* get_error() const noexcept; 122 123 private: 124 sd_bus_error error; 125 std::string full_message; 126 SdBusInterface* intf; 127 128 /** Populates the full_message from the stored 129 * error and the passed in prefix. */ 130 void populateMessage(std::string&& prefix); 131 132 /** Helper to reduce duplicate move logic */ 133 void move(SdBusError&& other); 134 }; 135 136 /** Exception for when an invalid conversion from string to enum is 137 * attempted. */ 138 struct InvalidEnumString final : public internal_exception 139 { 140 static constexpr auto errName = 141 "xyz.openbmc_project.sdbusplus.Error.InvalidEnumString"; 142 static constexpr auto errDesc = 143 "An enumeration mapping was attempted for which no valid enumeration " 144 "value exists."; 145 static constexpr auto errWhat = 146 "xyz.openbmc_project.sdbusplus.Error.InvalidEnumString: " 147 "An enumeration mapping was attempted for which no valid enumeration " 148 "value exists."; 149 150 const char* name() const noexcept override; 151 const char* description() const noexcept override; 152 const char* what() const noexcept override; 153 int get_errno() const noexcept override; 154 }; 155 156 /** Exception for when unpackProperties cannot find given property in provided 157 * container */ 158 class UnpackPropertyError final : public internal_exception 159 { 160 public: 161 UnpackPropertyError(std::string_view propertyName, 162 const UnpackErrorReason reason); 163 164 static constexpr auto errName = 165 "xyz.openbmc_project.sdbusplus.Error.UnpackPropertyError"; 166 static constexpr auto errDesc = 167 "unpackProperties failed to unpack one of requested properties."; 168 static constexpr auto errWhat = 169 "xyz.openbmc_project.sdbusplus.Error.UnpackPropertyError: " 170 "unpackProperties failed to unpack one of requested properties."; 171 172 const char* name() const noexcept override; 173 const char* description() const noexcept override; 174 const char* what() const noexcept override; 175 int get_errno() const noexcept override; 176 177 const std::string propertyName; 178 const UnpackErrorReason reason; 179 180 private: 181 const std::string errWhatDetailed; 182 }; 183 184 class UnhandledStop final : public internal_exception 185 { 186 public: 187 static constexpr auto errName = 188 "xyz.openbmc_project.sdbusplus.Error.UnhandledStop"; 189 static constexpr auto errDesc = 190 "An async Sender failed to handle a stop condition."; 191 static constexpr auto errWhat = 192 "xyz.openbmc_project.sdbusplus.Error.UnhandledStop: " 193 "An async Sender failed to handle a stop condition."; 194 195 const char* name() const noexcept override; 196 const char* description() const noexcept override; 197 const char* what() const noexcept override; 198 int get_errno() const noexcept override; 199 }; 200 201 } // namespace exception 202 203 using exception_t = exception::exception; 204 using internal_exception_t = exception::internal_exception; 205 206 } // namespace sdbusplus 207