Home Help Center

Passing proxy vs. passing identity in Glacier2

fconradyfconrady Member Florian ConradyOrganization: PersonalProject: RPC calls between hub and program extensions
I noticed that in Ice-3.5.1/py/demo/Glacier2/callback the RPC call passes the callback receiver proxy to the server, while in Ice-3.5.1/py/demo/Ice/bidir it passes only the identity and the callback receiver proxy is created from the identity.

I tried to change the Glacier2 callback example to pass the callback receiver's identity like in bidir, however, that makes both client, router and server crash without error messages. Do you know why?

Part changed in client:

class Client(Glacier2.Application):
def createSession(self):
session = None
try:
session = self.router().createSession('', '')
except Glacier2.PermissionDeniedException as ex:
print("permission denied:\n" + ex.reason)
except Glacier2.CannotCreateSessionException as ex:
print("cannot create session:\n" + ex.reason)
return session

def runWithSession(self, args):
if len(args) > 1:
print(self.appName() + ": too many arguments")
return 1

# Create proxy for callback object in server.
base = self.communicator().propertyToProxy('Callback.Proxy')
twoway = Demo.CallbackPrx.checkedCast(base)

# Create callback receiver object.
callbackReceiverIdent = self.createCallbackIdentity("callbackReceiver")
self.objectAdapter().add(CallbackReceiverI(), callbackReceiverIdent)

# Create callback receiver proxy to be sent to server.
twowayR = Demo.CallbackReceiverPrx.uncheckedCast(self.objectAdapter().createProxy(callbackReceiverIdent))

# Initiate callback from server, passing callback receiver identity.
twoway.initiateCallback(callbackReceiverIdent)

return 0


Part changed in server:

class CallbackI(Demo.Callback):
def __init__(self, communicator):
self._communicator = communicator

def initiateCallback(self, ident, current=None):
print("adding client `" + self._communicator.identityToString(ident) + "'")
client = Demo.CallbackReceiverPrx.uncheckedCast(current.con.createProxy(ident))
try:
client.callback()
except:
traceback.print_exc()


Changed interface:

#pragma once

#include <Ice/Identity.ice>

module Demo
{

interface CallbackReceiver
{
void callback();
};

interface Callback
{
void initiateCallback(Ice::Identity ident);
void shutdown();
};

};

Comments

  • benoitbenoit Rennes, FranceAdministrators, ZeroC Staff Benoit FoucherOrganization: ZeroC, Inc.Project: Ice ZeroC Staff
    Hi,

    I can't reproduce the crash. I'm getting a hang in the server but it's expected because the server thread pool has only one thread (bumping the number of threads to 2 with Ice.ThreadPool.Server.Size=2 fixes the hang).

    In any case, this won't work. This isn't how Glacier2 is supposed to be used. The server shouldn't use bi-directional connections for sending callbacks to the client through Glacier2. This will fail with an expected Ice::ObjectNotExistException (because Glacier2 doesn't setup the router -> server connection as a bi-dir connection).

    Why do you want to use bi-dir connections here?

    Cheers,
    Benoit.
  • fconradyfconrady Member Florian ConradyOrganization: PersonalProject: RPC calls between hub and program extensions
    Hi Benoit,

    >> I can't reproduce the crash. I'm getting a hang in the server but it's expected because the server thread pool has only one thread (bumping the number of threads to 2 with Ice.ThreadPool.Server.Size=2 fixes the hang).

    You are right, there is no crash, it's hanging. This is fixed when I increase the thread pool.

    >> The server shouldn't use bi-directional connections for sending callbacks to the client through Glacier2. This will fail with an expected Ice::ObjectNotExistException (because Glacier2 doesn't setup the router -> server connection as a bi-dir connection).

    After increasing the thread pool, I get the exception you mentioned. If I understand you correctly, the following would require a bidirectional connection between server and router

    client = Demo.CallbackReceiverPrx.uncheckedCast(current.con.createProxy(ident))
    client.callback()

    while passing the proxy itself (as an argument to initiateCallback) does not:

    proxy.callback()

    I believe you that there is a difference, but I do not quite understand why. In the first case I pass the identity from client to server and create the proxy in the server, while in the second case I create the proxy in the client and pass it to the server.

    Why does the router not understand how to forward a call to client.callback(), while it can do so for proxy.callback()? Why does the first case require a bidirectional connection between server and router, while the second case does not?

    Thanks
    Florian
  • benoitbenoit Rennes, FranceAdministrators, ZeroC Staff Benoit FoucherOrganization: ZeroC, Inc.Project: Ice ZeroC Staff
    Hi,

    In the first case, where you create the proxy with the Ice::Connection object using the identity, the request is sent over the connection established from Glacier2 to the server. From Glacier2's point of view, it's a "client" connection. This connection is not associated to any object adapter in Glacier2 and therefore when Glacier2 receives a request over this connection... it can't dispatch it because it can't find any servants for the request identity (in short: Glacier2 lacks the call to Ice::Connection::setAdapter which is necessary to setup the bi-dir connection).

    In the second case, you invoke on a proxy that contains the endpoints of the Glacier2 "server-side" object adapter (configured with Glacier2.Server.Endpoints). This connection is established from the server to Glacier2. From Glacier2's point of view it's a server connection dispatched with the Glacier2 server-side object adapter. It succeeds because Glacier2 dispatch invocations received over this object adapter endpoints and forwards them to the client.

    I hope this is clearer.

    Cheers,
    Benoit.
  • fconradyfconrady Member Florian ConradyOrganization: PersonalProject: RPC calls between hub and program extensions
    Hi Benoit,

    thanks, your explanation and some more reading in the manual made it clear. When I create the proxy in the client using

    Glacier2.Application.objectAdapter().createProxy(ident)

    it contains information about the endpoints of the server-side object adapter of the router. On the other hand, when I do

    current.con.createProxy(ident)

    in the callback sender in the server, the proxy is based on the connection from router to server. This connection is unidirectional and not associated with any object adapter in the router.

    Thanks
    Florian
Sign In or Register to comment.