I have the following situation; My Pyro4 project has a server and a client. The server contains a method which need to call 2 callbacks on the same callback object. So class Callback
has two callback methods: Callback()
and SecondCallback()
. There is some delay between the calls of those callback methods. I've simulated this delay in my example by calling time.sleep
.
I need to set a timeout on Pyro4 (Pyro4.config.COMMTIMEOUT
), because without one, the Pyro4 daemon will never break out of the requestLoop
method. This works perfectly when calling just one callback method, but when you have to call a second callback method, the Pyro4 callback daemon closes the connection after the first callback method was called + the timeout.
I've tried to set the timeout to a bigger amount, but this timeout is also the time the requestLoop
method blocks untill it processes the loopCondition.
An example script which demonstrates my issue is included below. You need to start it by starting a server after you started the Pyro4 nameserver:
python -m Pyro4.naming
python test.py -s
And afterwards starting a client in a new cmd window:
python test.py
Test.py
import Pyro4, time
from argparse import ArgumentParser
ip = "127.0.0.1"
class Server:
def __init__(self):
pass
def ActionOne(self):
return "Foo"
def ActionTwo(self):
return "Bar"
@Pyro4.oneway
def ActionThree(self, callback):
time.sleep(4)
callback.Callback()
time.sleep(3)
callback.SecondCallback()
class Callback:
def __init__(self):
self.Executed = False
pass
def Callback(self):
print "FooBar"
def SecondCallback(self):
print "raBooF"
self.Executed = True
def loopWhile(condition):
while condition:
time.sleep(.1)
if __name__ == "__main__":
parser = ArgumentParser()
parser.add_argument("--server", "-s", action="store_true")
args = parser.parse_args()
if(args.server):
print "Server"
daemon = Pyro4.core.Daemon(host=ip)
uri = daemon.register(Server())
ns = Pyro4.naming.locateNS(host=ip)
ns.register("server", uri)
daemon.requestLoop()
pass
else:
print "Client"
Pyro4.config.COMMTIMEOUT = .5
ns = Pyro4.naming.locateNS(host=ip)
serverUri = ns.lookup("server")
proxy = Pyro4.core.Proxy(serverUri)
print proxy.ActionOne()
print proxy.ActionTwo()
daemon = Pyro4.core.Daemon(host=ip)
callback = Callback()
daemon.register(callback)
proxy.ActionThree(callback)
daemon.requestLoop(lambda: not callback.Executed)
print "FINISHED"
The result of this script:
Server
:
Server
Exception in thread Thread-17:
Traceback (most recent call last):
File "C:\Program Files (x86)\IronPython 2.7\Lib\threading.py", line 552, in _T
hread__bootstrap_inner
self.run()
File "C:\Program Files (x86)\IronPython 2.7\Lib\threading.py", line 505, in ru
n
self.__target(*self.__args, **self.__kwargs)
File "test.py", line 22, in ActionThree
callback.SecondCallback()
File "C:\Program Files (x86)\IronPython 2.7\lib\site-packages\Pyro4\core.py",
line 171, in __call__
return self.__send(self.__name, args, kwargs)
File "C:\Program Files (x86)\IronPython 2.7\lib\site-packages\Pyro4\core.py",
line 410, in _pyroInvoke
msg = message.Message.recv(self._pyroConnection, [message.MSG_RESULT], hmac_
key=self._pyroHmacKey)
File "C:\Program Files (x86)\IronPython 2.7\lib\site-packages\Pyro4\message.py
", line 168, in recv
msg = cls.from_header(connection.recv(cls.header_size))
File "C:\Program Files (x86)\IronPython 2.7\lib\site-packages\Pyro4\socketutil
.py", line 448, in recv
return receiveData(self.sock, size)
File "C:\Program Files (x86)\IronPython 2.7\lib\site-packages\Pyro4\socketutil
.py", line 190, in receiveData
raise ConnectionClosedError("receiving: connection lost: " + str(x))
ConnectionClosedError: receiving: connection lost: [Errno 10022] A request to se
nd or receive data was disallowed because the socket is not connected and (when
sending on a datagram socket using a sendto call) no address was supplied
Client
:
Client
Foo
Bar
FooBar
My final question is: How do I prevent Pyro4 from closing the connection after COMMTIMEOUT expired when a second callback is called?
I hope all this information is clear enough to understand.
Thank you for your help.
For future reference:
I was able to restart the connection to the callback by calling:
callback._pyroReconnect()
Just before calling the second callback method