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