Problems with device dynamic attributes and wrong error messages

Hi,

After migrating from (py)tango 9.3 to 10.0 we have noticed problems with reading dynamic attributes when we create three or more devices with different dynamic attributes of the same class. The issue was noticed in sardana sardana-org/sardana#2027

It looks like they are two problems

  • starting from tango 9.5 in some cases dynamic attributes cannot be read. This issue is not related to tango server side, i.e. the reading on some dynamic attributes returns has_failed=True (to cure it one needs to remove other devices of the same class). The issue is connected to cppTango#814 but it looks like tango 9.3 is working much better than 9.5 and 10.0 (in this case)
  • the error messages are messed up e.g. when I try to read EnergyThreshold attribute the error message is related to CountTime
In [1]: import tango

In [2]: dp = tango.DeviceProxy("expchan/lambdalambdactrl/1")

In [3]: dp.EnergyThreshold
---------------------------------------------------------------------------
DevFailed                                 Traceback (most recent call last)
Cell In [3], line 1
----> 1 dp.EnergyThreshold

File /usr/lib/python3/dist-packages/tango/device_proxy.py:485, in __DeviceProxy__getattr(self, name)
    483 attr_info = self.__get_attr_cache().get(name_l)
    484 if attr_info:
--> 485     return __get_attribute_value(self, attr_info, name)
    487 try:
    488     self.__refresh_pipe_cache()

File /usr/lib/python3/dist-packages/tango/device_proxy.py:400, in __get_attribute_value(self, attr_info, name)
    398     return __async_get_attribute_value(self, attr_info, name)
    399 else:
--> 400     return __sync_get_attribute_value(self, attr_info, name)

File /usr/lib/python3/dist-packages/tango/device_proxy.py:392, in __sync_get_attribute_value(self, attr_info, name)
    391 def __sync_get_attribute_value(self, attr_info, name):
--> 392     attr_value = self.read_attribute(name).value
    393     return __update_enum_values(attr_info, attr_value)

File /usr/lib/python3/dist-packages/tango/green.py:226, in green.<locals>.decorator.<locals>.greener(obj, *args, **kwargs)
    224 green_mode = access("green_mode", None)
    225 executor = get_object_executor(obj, green_mode)
--> 226 return executor.run(fn, args, kwargs, wait=wait, timeout=timeout)

File /usr/lib/python3/dist-packages/tango/green.py:116, in AbstractExecutor.run(self, fn, args, kwargs, wait, timeout)
    114 # Synchronous (no delegation)
    115 if not self.asynchronous or not self.in_executor_context():
--> 116     return fn(*args, **kwargs)
    117 # Asynchronous delegation
    118 accessor = self.delegate(fn, *args, **kwargs)

File /usr/lib/python3/dist-packages/tango/device_proxy.py:594, in __DeviceProxy__read_attribute(self, value, extract_as)
    593 def __DeviceProxy__read_attribute(self, value, extract_as=ExtractAs.Numpy):
--> 594     return __check_read_attribute(self._read_attribute(value, extract_as))

File /usr/lib/python3/dist-packages/tango/device_proxy.py:160, in __check_read_attribute(dev_attr)
    158 def __check_read_attribute(dev_attr):
    159     if dev_attr.has_failed:
--> 160         raise DevFailed(*dev_attr.get_err_stack())
    161     return dev_attr

DevFailed: DevFailed[
DevError[
    desc = __wrapped_read_CountTime__read_DynamicAttribute__ method not found for EnergyThreshold
  origin = PyTango::Attr::read
  reason = PyTango_ReadAttributeMethodNotFound
severity = ERR]

DevError[
    desc = Failed to read_attribute on device expchan/lambdalambdactrl/1, attribute EnergyThreshold
  origin = virtual Tango::DeviceAttribute Tango::DeviceProxy::read_attribute(const std::string&) at (./lib/cpp/src/client/devapi_base.cpp:5673)
  reason = API_AttributeFailed
severity = ERR]
]

In [4]: dp._read_attribute("EnergyThreshold")
Out[4]: DeviceAttribute(data_format = tango._tango.AttrDataFormat.FMT_UNKNOWN, dim_x = 0, dim_y = 0, has_failed = True, is_empty = True, name = 'EnergyThreshold', nb_read = 0, nb_written = 0, quality = tango._tango.AttrQuality.ATTR_INVALID, r_dimension = AttributeDimension(dim_x = 0, dim_y = 0), time = TimeVal(tv_nsec = 0, tv_sec = 0, tv_usec = 0), type = tango._tango.CmdArgType(100), value = None, w_dim_x = 0, w_dim_y = 0, w_dimension = AttributeDimension(dim_x = 0, dim_y = 0), w_value = None)

In [5]: dp.read_attribute("EnergyThreshold")
---------------------------------------------------------------------------
DevFailed                                 Traceback (most recent call last)
Cell In [5], line 1
----> 1 dp.read_attribute("EnergyThreshold")

File /usr/lib/python3/dist-packages/tango/green.py:226, in green.<locals>.decorator.<locals>.greener(obj, *args, **kwargs)
    224 green_mode = access("green_mode", None)
    225 executor = get_object_executor(obj, green_mode)
--> 226 return executor.run(fn, args, kwargs, wait=wait, timeout=timeout)

File /usr/lib/python3/dist-packages/tango/green.py:116, in AbstractExecutor.run(self, fn, args, kwargs, wait, timeout)
    114 # Synchronous (no delegation)
    115 if not self.asynchronous or not self.in_executor_context():
--> 116     return fn(*args, **kwargs)
    117 # Asynchronous delegation
    118 accessor = self.delegate(fn, *args, **kwargs)

File /usr/lib/python3/dist-packages/tango/device_proxy.py:594, in __DeviceProxy__read_attribute(self, value, extract_as)
    593 def __DeviceProxy__read_attribute(self, value, extract_as=ExtractAs.Numpy):
--> 594     return __check_read_attribute(self._read_attribute(value, extract_as))

File /usr/lib/python3/dist-packages/tango/device_proxy.py:160, in __check_read_attribute(dev_attr)
    158 def __check_read_attribute(dev_attr):
    159     if dev_attr.has_failed:
--> 160         raise DevFailed(*dev_attr.get_err_stack())
    161     return dev_attr

DevFailed: DevFailed[
DevError[
    desc = __wrapped_read_CountTime__read_DynamicAttribute__ method not found for EnergyThreshold
  origin = PyTango::Attr::read
  reason = PyTango_ReadAttributeMethodNotFound
severity = ERR]

DevError[
    desc = Failed to read_attribute on device expchan/lambdalambdactrl/1, attribute EnergyThreshold
  origin = virtual Tango::DeviceAttribute Tango::DeviceProxy::read_attribute(const std::string&) at (./lib/cpp/src/client/devapi_base.cpp:5673)
  reason = API_AttributeFailed
severity = ERR]
]

In [6]: dp._read_attribute("EnergyThreshold")
Out[6]: DeviceAttribute(data_format = tango._tango.AttrDataFormat.FMT_UNKNOWN, dim_x = 0, dim_y = 0, has_failed = True, is_empty = True, name = 'EnergyThreshold', nb_read = 0, nb_written = 0, quality = tango._tango.AttrQuality.ATTR_INVALID, r_dimension = AttributeDimension(dim_x = 0, dim_y = 0), time = TimeVal(tv_nsec = 0, tv_sec = 0, tv_usec = 0), type = tango._tango.CmdArgType(100), value = None, w_dim_x = 0, w_dim_y = 0, w_dimension = AttributeDimension(dim_x = 0, dim_y = 0), w_value = None)

i.e. dev_attr.get_err_stack() provides a wrong error message.

The behavior is quite random so I would call it a bug (not a feature).

We have noticed this problems for tango servers (Pool, Pilc2-dev) written in python but probably the issue is related to changes cpptango (between 9.3 and 9.5).

Best, Jan

Edited by Jan Kotanski