Skip to content

DeviceProxy async methods inconsistency (should return error)

Hello,

I was working on this PyTango issue: pytango#590 (closed)

so I investigated different behaviour of *_async methods with callback in PUSH_CALLBACK model and there seems to be inconsistency.

When I throw an exception inside a command, my callback receives event with err property set to True (like expected). But when I throw exception in the attribute, the callback passed to read_attribute_asynch receives event with err property set to False, just like nothing wrong happened.

Here's a demonstration written in PyTango, but the same applies to CppTango where it originates:

import time

import tango
from tango.server import command, Device, attribute
from tango.test_utils import DeviceTestContext

from concurrent.futures import Future


class ServerForAsynchClients(Device):

    @command(dtype_in=int, dtype_out=int)
    def cmd_timeout(self, arg):
        time.sleep(2)
        return arg

    @command(dtype_in=int, dtype_out=int)
    def cmd_exception(self, arg):
        raise Exception("Intentional exception")

    @attribute(dtype=int)
    def attr_timeout(self):
        time.sleep(2)
        return 123

    @attribute(dtype=int)
    def attr_exception(self):
        raise Exception("Intentional exception")


with DeviceTestContext(ServerForAsynchClients, process=True) as proxy:
    tango.ApiUtil.instance().set_asynch_cb_sub_model(tango.cb_sub_model.PUSH_CALLBACK)
    proxy.set_timeout_millis(1000)
    # Command with exception returns error to callback
    future = Future()
    proxy.command_inout_asynch("cmd_exception", 123, future.set_result)
    result = future.result(timeout=5)
    assert result.err == True
    # Command with timeout returns error to callback
    future = Future()
    proxy.command_inout_asynch("cmd_timeout", 123, future.set_result)
    result = future.result(timeout=5)
    assert result.err == True
    # Read attribute with exception DOESN'T indicate error to callback (but probably should?)
    future = Future()
    proxy.read_attribute_asynch("attr_exception", future.set_result)
    result = future.result(timeout=5)
    assert result.err == False # This should fail, but it doesn't
    assert result.argout[0].has_failed == True # Instead we get report like this.
    # Read attribute with timeout fails for PyTango completely
    # But with CppTango client it works and returns error to callback
    # After fixing this part, so it don't crash, the result.err is set to True (consistently with command_inout_asynch)
    # future = Future()
    # proxy.read_attribute_asynch("attr_timeout", future.set_result)
    # result = future.result(timeout=5)
    # assert result.err == True
Edited by Mateusz Celary