Gevent Client times out

I'm writing an instrument server for a detector. For this I want the server to use gevent for asynchronous operation. A minimal model for my server looks like this:


import tango
from tango import AttrQuality, AttrWriteType, DispLevel, DevState, DebugIt, DevULong, GreenMode
from tango.server import Device, DeviceMeta, attribute, command, pipe, device_property

class EigerDectris(Device):
'''Eiger Detektor Server.'''

#Defining the basic device properties for connecting to the server API
api_version = device_property(dtype=str, default_value= '1.6.0')
ip_address = device_property(dtype=str, default_value= '10.42.41.10')

__metaclass__ = DeviceMeta
green_mode = GreenMode.Gevent

@command
def wait(self):
i = 0
while(i < 60):
print(i)
sleep(1)
i += 1

def init_device(self):
self._cache_values = {}
super(EigerDectris, self).init_device()

if __name__ == '__main__':
EigerDectris.run_server()


Some requests to the detector take a long tame (several seconds) to simulate this i use the "wait" command. The Client I wrote to test this looks like this:

from tango.gevent import DeviceProxy

if __name__ == '__main__':
dev = DeviceProxy('tango://saxssans:10000/saxssans/detector/eiger',wait = False)
d = dev.get()
wait = d.command_inout('wait', timeout = None)


When doing this i get TimeOutErrors. What am I doing wrong here?
Im using Ubuntu 18.04 with the following packages:
Python 2.7.15
tango 9.2.2
gevent 1.0
Hi KGoetz,

Where does sleep() method come from?

Is it from the time module?

Note that you must use gevent.sleep(), not time.sleep().

I am no PyTango expert but out of curiosity, I went to PyTango documentation and I saw this on this page (https://pytango.readthedocs.io/en/stable/green_modes/green.html#gevent-mode):

The list of methods that have been modified to accept gevent semantics are, on the tango.gevent.DeviceProxy():

Constructor
state()
status()
read_attribute()
write_attribute()
write_read_attribute()
read_attributes()
write_attributes()
ping()

I don't see command_inout in this list…
So I see at least 3 possibilities:

  1. Error in the documentation?
  2. Not implemented?
  3. Reynald does not understand anything in PyTango

We should not exclude the last possibility… smile

Hoping this helps,
Reynald
Rosenberg's Law: Software is easy to make, except when you want it to do something new.
Corollary: The only software that's worth making is software that does something new.
Hi TCoutInho,

changing the sleep command to gevent.sleep does not change anything. Afaik it shouldn't even be necessary with gevent. The server works as intended. While the wait command is running other Clients can connect and make calls to commands or attributes. That's all working fine.
The problem is, that no matter how I try to define the DeviceProxy, I get this TimeOutError when executing the wait command:
PyTango.CommunicationFailed: DevFailed[
DevError[
desc = TRANSIENT CORBA system exception: TRANSIENT_CallTimedout
origin = Connection::command_inout()
reason = API_CorbaException
severity = ERR]

DevError[
desc = Timeout (3000 mS) exceeded on device saxssans/detector/eiger, command wait
origin = Connection::command_inout()
reason = API_DeviceTimedOut
severity = ERR]
]


For my use I don't need asynchronous computing on the client side. Additionally when I try to create a normal tango DeviceProxy like this:
dev = DeviceProxy('tango://saxssans:10000/saxssans/detector/eiger', wait = True, timeout = None)

I get this error message:
File "./server_test_2.py", line 23, in <module>
dev = DeviceProxy('tango://saxssans:10000/saxssans/detector/eiger', wait = True, timeout = None)
File "/usr/local/lib/python2.7/dist-packages/tango/device_proxy.py", line 170, in __DeviceProxy__init__
return DeviceProxy.__init_orig__(self, *args, **kwargs)
Boost.Python.ArgumentError: Python argument types in
DeviceProxy.__init__(DeviceProxy, str)
did not match C++ signature:
__init__(boost::python::api::object, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool)
__init__(boost::python::api::object, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)
__init__(_object*, Tango::DeviceProxy)
__init__(_object*, char const*, bool)
__init__(_object*, char const*)
__init__(_object*)


My version of boost is 1.65.1
Edited 2 months ago
Disclaimer: I am a PyTango newbee… Sorry if I add some confusion to this thread…

The doc says the following about the command_inout Timeout parameter:

The number of seconds to wait for the result. If None, then there is no limit on the wait time. Ignored when green_mode is Synchronous or wait is False.

From what I understood while playing a bit with the code you provided and by reading the documentation, it seems like this timeout parameter given to command_inout method is actually different than the Tango client side timeout (Timeout involved in the CORBA communication) associated with your DeviceProxy.

If you execute:
d.get_timeout_millis()


You will see that it is set to 3000 ms, which is the default value, and which corresponds to the value you see in the error message.

Moreover, if you execute:
wait = d.command_inout('wait', timeout = 2)


You will not get the same error, at least not immediately. You will first get an error ending with:
gevent.timeout.Timeout: 2 seconds


Clearly showing that we have distinct timeouts involved here.

If you set your DeviceProxy client timeout to something big, you will not get any longer this error.
d.set_timeout_millis(100000)


This client side timeout is different than the one given to DeviceProxy constructor according to https://pytango.readthedocs.io/en/stable/client_api/green.html#tango.gevent.DeviceProxy

Hoping this helps a bit…
Rosenberg's Law: Software is easy to make, except when you want it to do something new.
Corollary: The only software that's worth making is software that does something new.
Hi Reynald,

thanks. Who thought it could be this easy. I would have never thought that the timeout I set in the constructor would be a different one than the one that I needed.

When setting the timeout with
d.set_timeout_millis()

everything works as I want it to.
 
Register or login to create to post a reply.