| Brad Bishop | 613a5b3 | 2017-01-05 20:58:13 -0500 | [diff] [blame] | 1 | /** | 
|  | 2 | * Copyright © 2016 IBM Corporation | 
|  | 3 | * | 
|  | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | * you may not use this file except in compliance with the License. | 
|  | 6 | * You may obtain a copy of the License at | 
|  | 7 | * | 
|  | 8 | *     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | * | 
|  | 10 | * Unless required by applicable law or agreed to in writing, software | 
|  | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | * See the License for the specific language governing permissions and | 
|  | 14 | * limitations under the License. | 
|  | 15 | */ | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 16 | #include <algorithm> | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 17 | #include <cerrno> | 
| Brad Bishop | 613a5b3 | 2017-01-05 20:58:13 -0500 | [diff] [blame] | 18 | #include <cstdlib> | 
| Brad Bishop | 08379a3 | 2017-03-06 21:28:46 -0500 | [diff] [blame] | 19 | #include <experimental/filesystem> | 
| Brad Bishop | 68c43b2 | 2017-08-28 16:24:00 -0400 | [diff] [blame] | 20 | #include <fstream> | 
| Brad Bishop | 613a5b3 | 2017-01-05 20:58:13 -0500 | [diff] [blame] | 21 | #include <memory> | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 22 | #include <thread> | 
| Brad Bishop | 613a5b3 | 2017-01-05 20:58:13 -0500 | [diff] [blame] | 23 | #include "sysfs.hpp" | 
| Brad Bishop | 613a5b3 | 2017-01-05 20:58:13 -0500 | [diff] [blame] | 24 |  | 
| Brad Bishop | f4bf63a | 2017-08-28 15:39:19 -0400 | [diff] [blame] | 25 | using namespace std::string_literals; | 
| Brandon Wyman | 8af8a20 | 2017-05-31 18:26:30 -0500 | [diff] [blame] | 26 | namespace fs = std::experimental::filesystem; | 
| Matthew Barth | 048ac87 | 2017-03-09 14:36:08 -0600 | [diff] [blame] | 27 |  | 
| Patrick Venture | 1e6324f | 2017-06-01 14:07:05 -0700 | [diff] [blame] | 28 | namespace sysfs { | 
|  | 29 |  | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 30 | static constexpr auto retryableErrors = { | 
|  | 31 | /* | 
|  | 32 | * Retry on bus or device errors or timeouts in case | 
|  | 33 | * they are transient. | 
|  | 34 | */ | 
|  | 35 | EIO, | 
|  | 36 | ETIMEDOUT, | 
|  | 37 |  | 
|  | 38 | /* | 
|  | 39 | * Retry CRC errors. | 
|  | 40 | */ | 
|  | 41 | EBADMSG, | 
|  | 42 |  | 
|  | 43 | /* | 
|  | 44 | * Some hwmon drivers do this when they aren't ready | 
|  | 45 | * instead of blocking.  Retry. | 
|  | 46 | */ | 
|  | 47 | EAGAIN, | 
|  | 48 | /* | 
|  | 49 | * We'll see this when for example i2c devices are | 
|  | 50 | * unplugged but the driver is still bound.  Retry | 
|  | 51 | * rather than exit on the off chance the device is | 
|  | 52 | * plugged back in and the driver doesn't do a | 
|  | 53 | * remove/probe.  If a remove does occur, we'll | 
|  | 54 | * eventually get ENOENT. | 
|  | 55 | */ | 
|  | 56 | ENXIO, | 
| Matt Spinler | 8a37c4b | 2017-10-04 15:53:56 -0500 | [diff] [blame] | 57 |  | 
|  | 58 | /* | 
| Matt Spinler | 67ce4a4 | 2017-11-16 13:03:16 -0600 | [diff] [blame] | 59 | * Some devices return this when they are busy doing | 
|  | 60 | * something else.  Even if being busy isn't the cause, | 
|  | 61 | * a retry still gives this app a shot at getting data | 
|  | 62 | * as opposed to failing out on the first try. | 
|  | 63 | */ | 
|  | 64 | ENODATA, | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 65 | }; | 
|  | 66 |  | 
| Brad Bishop | f4bf63a | 2017-08-28 15:39:19 -0400 | [diff] [blame] | 67 | static const auto emptyString = ""s; | 
| Brandon Wyman | 8af8a20 | 2017-05-31 18:26:30 -0500 | [diff] [blame] | 68 | static constexpr auto ofRoot = "/sys/firmware/devicetree/base"; | 
|  | 69 |  | 
| Brad Bishop | f4bf63a | 2017-08-28 15:39:19 -0400 | [diff] [blame] | 70 | std::string findPhandleMatch( | 
|  | 71 | const std::string& iochanneldir, | 
|  | 72 | const std::string& phandledir) | 
| Brad Bishop | 613a5b3 | 2017-01-05 20:58:13 -0500 | [diff] [blame] | 73 | { | 
| Brad Bishop | f4bf63a | 2017-08-28 15:39:19 -0400 | [diff] [blame] | 74 | // TODO: At the moment this method only supports device trees | 
|  | 75 | // with iio-hwmon nodes with a single sensor.  Typically | 
|  | 76 | // device trees are defined with all the iio sensors in a | 
|  | 77 | // single iio-hwmon node so it would be nice to add support | 
|  | 78 | // for lists of phandles (with variable sized entries) via | 
|  | 79 | // libfdt or something like that, so that users are not | 
|  | 80 | // forced into implementing unusual looking device trees | 
|  | 81 | // with multiple iio-hwmon nodes - one for each sensor. | 
|  | 82 |  | 
|  | 83 | fs::path ioChannelsPath{iochanneldir}; | 
|  | 84 | ioChannelsPath /= "io-channels"; | 
|  | 85 |  | 
|  | 86 | if (!fs::exists(ioChannelsPath)) | 
|  | 87 | { | 
|  | 88 | return emptyString; | 
|  | 89 | } | 
|  | 90 |  | 
|  | 91 | uint32_t ioChannelsValue; | 
|  | 92 | std::ifstream ioChannelsFile(ioChannelsPath); | 
|  | 93 |  | 
|  | 94 | ioChannelsFile.read( | 
|  | 95 | reinterpret_cast<char*>(&ioChannelsValue), | 
|  | 96 | sizeof(ioChannelsValue)); | 
|  | 97 |  | 
| Brandon Wyman | 8af8a20 | 2017-05-31 18:26:30 -0500 | [diff] [blame] | 98 | for (const auto& ofInst : fs::recursive_directory_iterator(phandledir)) | 
| Brad Bishop | 613a5b3 | 2017-01-05 20:58:13 -0500 | [diff] [blame] | 99 | { | 
| Brandon Wyman | 8af8a20 | 2017-05-31 18:26:30 -0500 | [diff] [blame] | 100 | auto path = ofInst.path(); | 
| Brad Bishop | f4bf63a | 2017-08-28 15:39:19 -0400 | [diff] [blame] | 101 | if ("phandle" != path.filename()) | 
| Brad Bishop | 613a5b3 | 2017-01-05 20:58:13 -0500 | [diff] [blame] | 102 | { | 
| Brad Bishop | f4bf63a | 2017-08-28 15:39:19 -0400 | [diff] [blame] | 103 | continue; | 
|  | 104 | } | 
|  | 105 | std::ifstream pHandleFile(path); | 
|  | 106 | uint32_t pHandleValue; | 
| Brandon Wyman | 4eb9858 | 2017-05-24 14:24:00 -0500 | [diff] [blame] | 107 |  | 
| Brad Bishop | f4bf63a | 2017-08-28 15:39:19 -0400 | [diff] [blame] | 108 | pHandleFile.read( | 
|  | 109 | reinterpret_cast<char*>(&pHandleValue), | 
|  | 110 | sizeof(pHandleValue)); | 
| Brandon Wyman | 4eb9858 | 2017-05-24 14:24:00 -0500 | [diff] [blame] | 111 |  | 
| Brad Bishop | f4bf63a | 2017-08-28 15:39:19 -0400 | [diff] [blame] | 112 | if (ioChannelsValue == pHandleValue) | 
|  | 113 | { | 
|  | 114 | return path; | 
| Brandon Wyman | 8af8a20 | 2017-05-31 18:26:30 -0500 | [diff] [blame] | 115 | } | 
|  | 116 | } | 
|  | 117 |  | 
| Brad Bishop | f4bf63a | 2017-08-28 15:39:19 -0400 | [diff] [blame] | 118 | return emptyString; | 
| Brandon Wyman | 8af8a20 | 2017-05-31 18:26:30 -0500 | [diff] [blame] | 119 | } | 
|  | 120 |  | 
| Brad Bishop | 431d26a | 2017-08-25 09:47:58 -0400 | [diff] [blame] | 121 | std::string findCalloutPath(const std::string& instancePath) | 
| Brandon Wyman | 8af8a20 | 2017-05-31 18:26:30 -0500 | [diff] [blame] | 122 | { | 
| Brad Bishop | 431d26a | 2017-08-25 09:47:58 -0400 | [diff] [blame] | 123 | // Follow the hwmon instance (/sys/class/hwmon/hwmon<N>) | 
|  | 124 | // /sys/devices symlink. | 
|  | 125 | fs::path devPath{instancePath}; | 
|  | 126 | devPath /= "device"; | 
| Brandon Wyman | 8af8a20 | 2017-05-31 18:26:30 -0500 | [diff] [blame] | 127 |  | 
| Brad Bishop | 431d26a | 2017-08-25 09:47:58 -0400 | [diff] [blame] | 128 | try | 
| Brandon Wyman | 8af8a20 | 2017-05-31 18:26:30 -0500 | [diff] [blame] | 129 | { | 
| Brad Bishop | 431d26a | 2017-08-25 09:47:58 -0400 | [diff] [blame] | 130 | devPath = fs::canonical(devPath); | 
|  | 131 | } | 
|  | 132 | catch (const std::system_error& e) | 
|  | 133 | { | 
|  | 134 | return emptyString; | 
|  | 135 | } | 
|  | 136 |  | 
|  | 137 | // See if the device is backed by the iio-hwmon driver. | 
|  | 138 | fs::path p{devPath}; | 
|  | 139 | p /= "driver"; | 
|  | 140 | p = fs::canonical(p); | 
|  | 141 |  | 
|  | 142 | if (p.filename() != "iio_hwmon") | 
|  | 143 | { | 
|  | 144 | // Not backed by iio-hwmon.  The device pointed to | 
|  | 145 | // is the callout device. | 
|  | 146 | return devPath; | 
|  | 147 | } | 
|  | 148 |  | 
|  | 149 | // Find the DT path to the iio-hwmon platform device. | 
|  | 150 | fs::path ofDevPath{devPath}; | 
|  | 151 | ofDevPath /= "of_node"; | 
|  | 152 |  | 
|  | 153 | try | 
|  | 154 | { | 
|  | 155 | ofDevPath = fs::canonical(ofDevPath); | 
|  | 156 | } | 
|  | 157 | catch (const std::system_error& e) | 
|  | 158 | { | 
|  | 159 | return emptyString; | 
|  | 160 | } | 
|  | 161 |  | 
|  | 162 | // Search /sys/bus/iio/devices for the phandle in io-channels. | 
|  | 163 | // If a match is found, use the corresponding /sys/devices | 
|  | 164 | // iio device as the callout device. | 
|  | 165 | static constexpr auto iioDevices = "/sys/bus/iio/devices"; | 
|  | 166 | for (const auto& iioDev: fs::recursive_directory_iterator(iioDevices)) | 
|  | 167 | { | 
|  | 168 | p = iioDev.path(); | 
|  | 169 | p /= "of_node"; | 
|  | 170 |  | 
|  | 171 | try | 
|  | 172 | { | 
|  | 173 | p = fs::canonical(p); | 
|  | 174 | } | 
|  | 175 | catch (const std::system_error& e) | 
|  | 176 | { | 
|  | 177 | continue; | 
|  | 178 | } | 
|  | 179 |  | 
|  | 180 | auto match = findPhandleMatch(ofDevPath, p); | 
|  | 181 | auto n = match.rfind('/'); | 
| Brandon Wyman | 8af8a20 | 2017-05-31 18:26:30 -0500 | [diff] [blame] | 182 | if (n != std::string::npos) | 
|  | 183 | { | 
| Brad Bishop | 431d26a | 2017-08-25 09:47:58 -0400 | [diff] [blame] | 184 | // This is the iio device referred to by io-channels. | 
|  | 185 | // Remove iio:device<N>. | 
|  | 186 | try | 
|  | 187 | { | 
|  | 188 | return fs::canonical(iioDev).parent_path(); | 
|  | 189 | } | 
|  | 190 | catch (const std::system_error& e) | 
|  | 191 | { | 
|  | 192 | return emptyString; | 
|  | 193 | } | 
| Brandon Wyman | 8af8a20 | 2017-05-31 18:26:30 -0500 | [diff] [blame] | 194 | } | 
|  | 195 | } | 
|  | 196 |  | 
| Brad Bishop | 431d26a | 2017-08-25 09:47:58 -0400 | [diff] [blame] | 197 | return emptyString; | 
| Brandon Wyman | 8af8a20 | 2017-05-31 18:26:30 -0500 | [diff] [blame] | 198 | } | 
|  | 199 |  | 
|  | 200 | std::string findHwmon(const std::string& ofNode) | 
|  | 201 | { | 
|  | 202 | static constexpr auto hwmonRoot = "/sys/class/hwmon"; | 
|  | 203 |  | 
|  | 204 | fs::path fullOfPath{ofRoot}; | 
|  | 205 | fullOfPath /= ofNode; | 
|  | 206 |  | 
|  | 207 | for (const auto& hwmonInst : fs::directory_iterator(hwmonRoot)) | 
|  | 208 | { | 
|  | 209 | auto path = hwmonInst.path(); | 
|  | 210 | path /= "of_node"; | 
| Brad Bishop | 4e24ebd | 2017-08-28 16:19:16 -0400 | [diff] [blame] | 211 |  | 
|  | 212 | try | 
| Brandon Wyman | 8af8a20 | 2017-05-31 18:26:30 -0500 | [diff] [blame] | 213 | { | 
| Brad Bishop | 4e24ebd | 2017-08-28 16:19:16 -0400 | [diff] [blame] | 214 | path = fs::canonical(path); | 
|  | 215 | } | 
|  | 216 | catch (const std::system_error& e) | 
|  | 217 | { | 
|  | 218 | // realpath may encounter ENOENT (Hwmon | 
|  | 219 | // instances have a nasty habit of | 
|  | 220 | // going away without warning). | 
|  | 221 | continue; | 
| Brad Bishop | 613a5b3 | 2017-01-05 20:58:13 -0500 | [diff] [blame] | 222 | } | 
|  | 223 |  | 
| Brad Bishop | 4e24ebd | 2017-08-28 16:19:16 -0400 | [diff] [blame] | 224 | if (path == fullOfPath) | 
|  | 225 | { | 
|  | 226 | return hwmonInst.path(); | 
|  | 227 | } | 
|  | 228 |  | 
|  | 229 | // Try to find HWMON instance via phandle values. | 
|  | 230 | // Used for IIO device drivers. | 
|  | 231 | auto matchpath = findPhandleMatch(path, fullOfPath); | 
|  | 232 | if (!matchpath.empty()) | 
|  | 233 | { | 
|  | 234 | return hwmonInst.path(); | 
|  | 235 | } | 
| Brad Bishop | 613a5b3 | 2017-01-05 20:58:13 -0500 | [diff] [blame] | 236 | } | 
|  | 237 |  | 
| Brad Bishop | 4e24ebd | 2017-08-28 16:19:16 -0400 | [diff] [blame] | 238 | return emptyString; | 
| Brad Bishop | 613a5b3 | 2017-01-05 20:58:13 -0500 | [diff] [blame] | 239 | } | 
|  | 240 |  | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 241 | namespace hwmonio | 
|  | 242 | { | 
|  | 243 |  | 
|  | 244 | HwmonIO::HwmonIO(const std::string& path) : p(path) | 
|  | 245 | { | 
|  | 246 |  | 
|  | 247 | } | 
|  | 248 |  | 
| Matt Spinler | fee106b | 2017-11-29 15:18:05 -0600 | [diff] [blame] | 249 | int64_t HwmonIO::read( | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 250 | const std::string& type, | 
|  | 251 | const std::string& id, | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 252 | const std::string& sensor, | 
|  | 253 | size_t retries, | 
|  | 254 | std::chrono::milliseconds delay) const | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 255 | { | 
| Matt Spinler | fee106b | 2017-11-29 15:18:05 -0600 | [diff] [blame] | 256 | int64_t val; | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 257 | std::ifstream ifs; | 
|  | 258 | auto fullPath = sysfs::make_sysfs_path( | 
|  | 259 | p, type, id, sensor); | 
|  | 260 |  | 
|  | 261 | ifs.exceptions( | 
|  | 262 | std::ifstream::failbit | | 
|  | 263 | std::ifstream::badbit | | 
|  | 264 | std::ifstream::eofbit); | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 265 |  | 
|  | 266 | while (true) | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 267 | { | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 268 | try | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 269 | { | 
| Matt Spinler | c8a8e01 | 2017-12-14 10:22:22 -0600 | [diff] [blame^] | 270 | errno = 0; | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 271 | if (!ifs.is_open()) | 
|  | 272 | ifs.open(fullPath); | 
|  | 273 | ifs.clear(); | 
|  | 274 | ifs.seekg(0); | 
|  | 275 | ifs >> val; | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 276 | } | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 277 | catch (const std::exception& e) | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 278 | { | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 279 | auto rc = errno; | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 280 |  | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 281 | if (!rc) | 
|  | 282 | { | 
|  | 283 | throw; | 
|  | 284 | } | 
|  | 285 |  | 
| Edward A. James | 26d2173 | 2017-11-30 13:17:26 -0600 | [diff] [blame] | 286 | if (rc == ENOENT || rc == ENODEV) | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 287 | { | 
| Edward A. James | 26d2173 | 2017-11-30 13:17:26 -0600 | [diff] [blame] | 288 | // If the directory or device disappeared then this application | 
|  | 289 | // should gracefully exit.  There are race conditions between the | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 290 | // unloading of a hwmon driver and the stopping of this service | 
|  | 291 | // by systemd.  To prevent this application from falsely failing | 
|  | 292 | // in these scenarios, it will simply exit if the directory or | 
|  | 293 | // file can not be found.  It is up to the user(s) of this | 
|  | 294 | // provided hwmon object to log the appropriate errors if the | 
|  | 295 | // object disappears when it should not. | 
|  | 296 | exit(0); | 
|  | 297 | } | 
|  | 298 |  | 
|  | 299 | if (0 == std::count( | 
|  | 300 | retryableErrors.begin(), | 
|  | 301 | retryableErrors.end(), | 
|  | 302 | rc) || | 
|  | 303 | !retries) | 
|  | 304 | { | 
|  | 305 | // Not a retryable error or out of retries. | 
|  | 306 |  | 
|  | 307 | // Work around GCC bugs 53984 and 66145 for callers by | 
|  | 308 | // explicitly raising system_error here. | 
|  | 309 | throw std::system_error(rc, std::generic_category()); | 
|  | 310 | } | 
|  | 311 |  | 
|  | 312 | --retries; | 
|  | 313 | std::this_thread::sleep_for(delay); | 
|  | 314 | continue; | 
|  | 315 | } | 
|  | 316 | break; | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 317 | } | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 318 |  | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 319 | return val; | 
|  | 320 | } | 
|  | 321 |  | 
|  | 322 | void HwmonIO::write( | 
|  | 323 | uint32_t val, | 
|  | 324 | const std::string& type, | 
|  | 325 | const std::string& id, | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 326 | const std::string& sensor, | 
|  | 327 | size_t retries, | 
|  | 328 | std::chrono::milliseconds delay) const | 
|  | 329 |  | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 330 | { | 
|  | 331 | std::ofstream ofs; | 
|  | 332 | auto fullPath = sysfs::make_sysfs_path( | 
|  | 333 | p, type, id, sensor); | 
|  | 334 |  | 
|  | 335 | ofs.exceptions( | 
|  | 336 | std::ofstream::failbit | | 
|  | 337 | std::ofstream::badbit | | 
|  | 338 | std::ofstream::eofbit); | 
|  | 339 |  | 
|  | 340 | // See comments in the read method for an explanation of the odd exception | 
|  | 341 | // handling behavior here. | 
|  | 342 |  | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 343 | while (true) | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 344 | { | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 345 | try | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 346 | { | 
| Matt Spinler | c8a8e01 | 2017-12-14 10:22:22 -0600 | [diff] [blame^] | 347 | errno = 0; | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 348 | if (!ofs.is_open()) | 
|  | 349 | ofs.open(fullPath); | 
|  | 350 | ofs.clear(); | 
|  | 351 | ofs.seekp(0); | 
|  | 352 | ofs << val; | 
|  | 353 | ofs.flush(); | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 354 | } | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 355 | catch (const std::exception& e) | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 356 | { | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 357 | auto rc = errno; | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 358 |  | 
| Brad Bishop | 754d38c | 2017-09-08 00:46:58 -0400 | [diff] [blame] | 359 | if (!rc) | 
|  | 360 | { | 
|  | 361 | throw; | 
|  | 362 | } | 
|  | 363 |  | 
|  | 364 | if (rc == ENOENT) | 
|  | 365 | { | 
|  | 366 | exit(0); | 
|  | 367 | } | 
|  | 368 |  | 
|  | 369 | if (0 == std::count( | 
|  | 370 | retryableErrors.begin(), | 
|  | 371 | retryableErrors.end(), | 
|  | 372 | rc) || | 
|  | 373 | !retries) | 
|  | 374 | { | 
|  | 375 | // Not a retryable error or out of retries. | 
|  | 376 |  | 
|  | 377 | // Work around GCC bugs 53984 and 66145 for callers by | 
|  | 378 | // explicitly raising system_error here. | 
|  | 379 | throw std::system_error(rc, std::generic_category()); | 
|  | 380 | } | 
|  | 381 |  | 
|  | 382 | --retries; | 
|  | 383 | std::this_thread::sleep_for(delay); | 
|  | 384 | continue; | 
|  | 385 | } | 
|  | 386 | break; | 
| Brad Bishop | 8b574a7 | 2017-08-25 16:17:19 -0400 | [diff] [blame] | 387 | } | 
|  | 388 | } | 
|  | 389 |  | 
|  | 390 | std::string HwmonIO::path() const | 
|  | 391 | { | 
|  | 392 | return p; | 
|  | 393 | } | 
|  | 394 |  | 
|  | 395 | } // namespace hwmonio | 
| Patrick Venture | 1e6324f | 2017-06-01 14:07:05 -0700 | [diff] [blame] | 396 | } | 
| Brad Bishop | 613a5b3 | 2017-01-05 20:58:13 -0500 | [diff] [blame] | 397 | // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 |