0

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.

Arnold Pistorius
  • 522
  • 4
  • 18

2 Answers2

0

For future reference:

I was able to restart the connection to the callback by calling:

callback._pyroReconnect()

Just before calling the second callback method

Arnold Pistorius
  • 522
  • 4
  • 18
0

Your question is a bit strange, to be honest.

On the one hand you're configuring COMMTIMEOUT to a (very low) value of 0.5 seconds, thereby enabling the concept of timeouts. On the other hand you're asking to not get a timeout that closes the connection on the server. What is it you want?

But yeah, you can use _pyroReconnect to reconnect a proxy that has been disconnected. Also see the readmes and code of the autoreconnect and disconnects examples that come with Pyro4.

Irmen de Jong
  • 2,739
  • 1
  • 14
  • 26
  • This time-out is on the client side and means that it will wait 500ms for response. In my case I am using callbacks, which acts as a server, therefore I find it a bit strange that the connection to the callback gets closed, but the connection with the proxy on the server not. – Arnold Pistorius Sep 11 '15 at 06:13
  • Your client code transfers full control to the daemon.requestLoop method and as such doesn't do anything anymore with the client proxy. So there's nothing to register any timeout to. – Irmen de Jong Sep 11 '15 at 18:39