Skip to content

Commit

Permalink
Update lm_sensors and catch specific errors. (#4667)
Browse files Browse the repository at this point in the history
This updates our copy of the libsensors Python bindings to the most
recent upstream copy, which provides proper errors instead of just
raising bare Exceptions, and updates our code to catch those errors
instead of catching bare exceptions.
  • Loading branch information
Ferroin committed Nov 15, 2018
1 parent 28b384e commit 9a071de
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 18 deletions.
93 changes: 81 additions & 12 deletions collectors/python.d.plugin/python_modules/third_party/lm_sensors.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,79 @@
_libc = cdll.LoadLibrary(ctypes.util.find_library("c"))
# see https://github.com/paroj/sensors.py/issues/1
_libc.free.argtypes = [c_void_p]

_hdl = cdll.LoadLibrary(ctypes.util.find_library("sensors"))

version = c_char_p.in_dll(_hdl, "libsensors_version").value.decode("ascii")


class SensorsError(Exception):
pass


class ErrorWildcards(SensorsError):
pass


class ErrorNoEntry(SensorsError):
pass


class ErrorAccessRead(SensorsError, PermissionError):
pass


class ErrorKernel(SensorError, OSError):
pass


class ErrorDivZero(SensorError, ZeroDivisionError):
pass


class ErrorChipName(SensorError):
pass


class ErrorBusName(SensorError):
pass


class ErrorParse(SensorError):
pass


class ErrorAccessWrite(SensorError, PermissionError):
pass


class ErrorIO(SensorError, IOError):
pass


class ErrorRecursion(SensorError):
pass


_ERR_MAP = {
1: ErrorWildcards,
2: ErrorNoEntry,
3: ErrorAccessRead,
4: ErrorKernel,
5: ErrorDivZero,
6: ErrorChipName,
7: ErrorBusName,
8: ErrorParse,
9: ErrorAccessWrite,
10: ErrorIO,
11: ErrorRecursion
}


def raise_sensor_error(errno, message=''):
raise _ERR_MAP[abs(errno)](message)


class bus_id(Structure):
_fields_ = [("type", c_short),
("nr", c_short)]
Expand Down Expand Up @@ -65,8 +133,8 @@ class subfeature(Structure):
_hdl.sensors_get_detected_chips.restype = POINTER(chip_name)
_hdl.sensors_get_features.restype = POINTER(feature)
_hdl.sensors_get_all_subfeatures.restype = POINTER(subfeature)
_hdl.sensors_get_label.restype = c_void_p # return pointer instead of str so we can free it
_hdl.sensors_get_adapter_name.restype = c_char_p # docs do not say whether to free this or not
_hdl.sensors_get_label.restype = c_void_p # return pointer instead of str so we can free it
_hdl.sensors_get_adapter_name.restype = c_char_p # docs do not say whether to free this or not
_hdl.sensors_strerror.restype = c_char_p

### RAW API ###
Expand All @@ -78,8 +146,9 @@ class subfeature(Structure):
def init(cfg_file=None):
file = _libc.fopen(cfg_file.encode("utf-8"), "r") if cfg_file is not None else None

if _hdl.sensors_init(file) != 0:
raise Exception("sensors_init failed")
result = _hdl.sensors_init(file)
if result != 0:
raise_sensor_error(result, "sensors_init failed")

if file is not None:
_libc.fclose(file)
Expand All @@ -94,7 +163,7 @@ def parse_chip_name(orig_name):
err = _hdl.sensors_parse_chip_name(orig_name.encode("utf-8"), byref(ret))

if err < 0:
raise Exception(strerror(err))
raise_sensor_error(err, strerror(err))

return ret

Expand Down Expand Up @@ -129,7 +198,7 @@ def chip_snprintf_name(chip, buffer_size=200):
err = _hdl.sensors_snprintf_chip_name(ret, buffer_size, byref(chip))

if err < 0:
raise Exception(strerror(err))
raise_sensor_error(err, strerror(err))

return ret.value.decode("utf-8")

Expand All @@ -140,7 +209,7 @@ def do_chip_sets(chip):
"""
err = _hdl.sensors_do_chip_sets(byref(chip))
if err < 0:
raise Exception(strerror(err))
raise_sensor_error(err, strerror(err))


def get_adapter_name(bus):
Expand Down Expand Up @@ -178,7 +247,7 @@ def get_value(chip, subfeature_nr):
val = c_double()
err = _hdl.sensors_get_value(byref(chip), subfeature_nr, byref(val))
if err < 0:
raise Exception(strerror(err))
raise_sensor_error(err, strerror(err))
return val.value


Expand All @@ -189,7 +258,7 @@ def set_value(chip, subfeature_nr, value):
val = c_double(value)
err = _hdl.sensors_set_value(byref(chip), subfeature_nr, byref(val))
if err < 0:
raise Exception(strerror(err))
raise_sensor_error(err, strerror(err))


### Convenience API ###
Expand All @@ -213,7 +282,7 @@ def __del__(self):
if self.match is not None:
free_chip_name(self.match)

def next(self): # python2 compability
def next(self): # python2 compability
return self.__next__()


Expand All @@ -233,7 +302,7 @@ def __next__(self):

return feature

def next(self): # python2 compability
def next(self): # python2 compability
return self.__next__()


Expand All @@ -254,5 +323,5 @@ def __next__(self):

return subfeature

def next(self): # python2 compability
def next(self): # python2 compability
return self.__next__()
10 changes: 4 additions & 6 deletions collectors/python.d.plugin/sensors/sensors.chart.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,7 @@ def get_data(self):
try:
val = sensors.get_value(chip, sf.number)
break
# TODO: use specific error after upstream is fixed
except Exception:
except sensors.SensorsError:
continue
if val is None:
continue
Expand All @@ -119,7 +118,7 @@ def get_data(self):
if val < limit[0] or val > limit[1]:
continue
data[prefix + '_' + str(feature.name.decode())] = int(val * 1000)
except Exception as error:
except sensors.SensorsError as error:
self.error(error)
return None

Expand All @@ -137,8 +136,7 @@ def create_definitions(self):
for sf in sfi:
try:
vals.append(sensors.get_value(chip, sf.number))
# TODO: use specific error after upstream is fixed
except Exception as error:
except sensors.SensorsError as error:
self.error('{0}: {1}'.format(sf.name, error))
continue
if not vals or vals[0] == 0:
Expand All @@ -160,7 +158,7 @@ def create_definitions(self):
def check(self):
try:
sensors.init()
except Exception as error:
except sensors.SensorsError as error:
self.error(error)
return False

Expand Down

0 comments on commit 9a071de

Please sign in to comment.