Archived

This forum has been archived. Please start a new discussion on GitHub.

IceTouch hangs with Glacier2

Hi,

I'm developing an IceTouch-based application. This application will actuate as a client (send data to other devices) and server (receive data from other devices). It will exist an intermediate server to store some data, and a Glacier2 service will be running in the same server to route the communication among the devices.

I have a problem when I try to create a Glacier2 session to connect to my server. I have a configuration file like this:
Ice.Default.Router=Glacier2/router:tcp -h IP_GLACIER_ROUTER -p 4063
Ice.ACM.Client=0
Ice.RetryIntervals=-1
Ice.Trace.Network=1
Ice.Trace.Protocol=1

AnnounceServer=MobileAnnounce -t:tcp -h IP_SERVER -p 8008
Ice.Override.Timeout=10000

The application creates a communicator using the configuration file:
        ICEInitializationData* initData = [ICEInitializationData initializationData];
        initData.properties = [ICEUtil createProperties];
        
        [initData.properties load:configFile];
        
        // Dispatch AMI callbacks on the main thread
        initData.dispatcher = ^(id<ICEDispatcherCall> call, id<ICEConnection> con)
        {
            dispatch_sync(dispatch_get_main_queue(), ^ { [call run]; });
        };
        
        self.communicator = [[ICEUtil createCommunicator:initData] retain];

After the communication is created, it is necessary to create a Glacier2 session, isn't it? I'm trying to do it this way:
        @try{
            // Create Glacier2 session
            ICERouterPrx *defRouter = [communicator getDefaultRouter];
            id<Glacier2RouterPrx> router = [Glacier2RouterPrx checkedCast:defRouter];
            id<Glacier2SessionPrx> session = [router createSession:@"" password:@""];
            
            adapter = [communicator createObjectAdapterWithRouter:@"MobileAnnounce" router:self.router];
            [adapter add:self identity:[communicator stringToIdentity:@"AnnounceServer"]];
            [adapter activate];            
        }
        @catch(Glacier2CannotCreateSessionException* ex)
        {
            NSLog(@"Glacier2CannotCreateSessionException");
        }
        @catch(Glacier2PermissionDeniedException* ex)
        {
            NSLog(@"Glacier2PermissionDeniedException");
        }
        @catch(ICEException* ex)
        {
            NSLog(@"Unknown exception");
        }

As you can see, I asynchronously try to get the router and a Glacier2 session. The problem is that when I do the checkedCast, the application hangs: the [router createSession...] method is never executed. You can see the output here:
2013-06-04 09:10:20.914 App[1949:4b03] [Network: tcp connection established
local address = 192.168.15.101:50752
remote address = IP_GLACIER_ROUTER:4063]
2013-06-04 09:10:20.981 App[1949:4b03] [Protocol: received validate connection 
message type = 3 (validate connection)
compression status = 0 (not compressed; do not compress response, if any)
message size = 14]

What am I doing wrong? The server-side is working properly, because I can connect to it using a pyhton application.

Thank you in advance

Comments

  • xdm
    xdm La Coruña, Spain
    Most likely the problem is that you are calling a synchronous method "checkedCast" from the main thread and your dispatcher try to dispatch the reply to this same thread, causing the hang. You shouldn't do any synchronous call from the main thread.

    The easier will be to move the session creation to a separate thread.
  • Thank you for your quick response.

    I embraced the above code with an async call, and now the application doesn't hang. But it is still not working. My new code is the following:
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^ {
            @try{
                // Create Glacier2 session
                self.glacierRouter = [Glacier2RouterPrx checkedCast:[communicator getDefaultRouter]];
                self.glacierSession = [self.glacierRouter createSession:@"" password:@""];
            }
            @catch(Glacier2CannotCreateSessionException* ex)
            {
                NSLog(@"Glacier2CannotCreateSessionException: %@", ex);
            }
            @catch(Glacier2PermissionDeniedException* ex)
            {
                NSLog(@"Glacier2PermissionDeniedException: %@", ex);
            }
            @catch(ICEException* ex)
            {
                NSLog(@"Unknown exception creating the Glacier session: \n%@", ex);
            }
    });
    

    Now, when the checkedCast method, I get this output:
    2013-06-04 12:16:02.526 App[5547:4b03] [Network: tcp connection established
    local address = 192.168.15.101:51329
    remote address = IP_SERVER:4063]
    2013-06-04 12:16:02.595 App[5547:4b03] [Protocol: received validate connection 
    message type = 3 (validate connection)
    compression status = 0 (not compressed; do not compress response, if any)
    message size = 14]
    2013-06-04 12:16:02.596 App[5547:c07] [Protocol: sending asynchronous request
    message type = 0 (request)
    compression status = 0 (not compressed; do not compress response, if any)
    message size = 58
    request id = 1
    identity = Glacier2/router
    facet = 
    operation = getClientProxy
    mode = 1 (nonmutating)
    context = ]
    2013-06-04 12:16:02.596 App[5547:1303] [Protocol: sending request 
    message type = 0 (request)
    compression status = 0 (not compressed; do not compress response, if any)
    message size = 70
    request id = 2
    identity = Glacier2/router
    facet = 
    operation = ice_isA
    mode = 1 (nonmutating)
    context = ]
    2013-06-04 12:16:02.597 App[5547:1b03] [Protocol: sending request 
    message type = 0 (request)
    compression status = 0 (not compressed; do not compress response, if any)
    message size = 70
    request id = 3
    identity = Glacier2/router
    facet = 
    operation = ice_isA
    mode = 1 (nonmutating)
    context = ]
    2013-06-04 12:16:02.670 App[5547:1303] Unknown exception: Transceiver.cpp:368: Ice::ConnectionLostException:
    connection lost: recv() returned zero
    

    Finally, an exception is caught:
    2013-06-04 12:16:41.883 App[5547:1b03] Unknown exception creating the Glacier session: 
    Transceiver.cpp:368: Ice::ConnectionLostException:
    connection lost: recv() returned zero
    

    Any idea?

    Thank you
  • xdm
    xdm La Coruña, Spain
    Hi,

    One possible cause for this is that your application is using the wrong Glacier2.InstanceName.

    Check you Glacier2 configuration file, according to the client properties you posted, the Glacier2.InstanceName should be "Glacier2"

    In the Ice.Default.Router proxy the identity category, should match the Glacier2.InstanceName of the Glacier2 configuration.
    #Client configuration
    Ice.Default.Router=Glacier2/router:tcp -h IP_GLACIER_ROUTER -p 4063
    
    #Glacier2 configuration
    Glacier2.InstanceName=Glacier2
    

    If that doesn't solve your issue, can you post you Glacier2 configuration file and log.

    Best Regards.
  • Glacier2.InstanceName wasn't in the glacier config file, but still doesn't work.

    The glacier config file is the following:
    Glacier2.Client.Endpoints=default -p 4063
    Glacier2.Server.Endpoints=default
    Glacier2.SessionTimeout=60
    Glacier2.PermissionsVerifier=Glacier2/NullPermissionsVerifier
    Glacier2.InstanceName=Glacier2
    Ice.Trace.Protocol=1
    Ice.Trace.Network=1
    Ice.Default.CollocationOptimized=0
    

    This is the Glacier2 log:
    -- 06/04/13 12:59:20.800 glacier2router: Network: listening for tcp connections 
    at :::4063
       local interfaces: GLACIER_LOCAL_IP, 127.0.0.1, 0:0:0:0:0:0:0:1
    -- 06/04/13 12:59:20.801 glacier2router: Network: published endpoints for object
     adapter `Glacier2.Client':
       tcp -h GLACIER_LOCAL_IP -p 4063
    -- 06/04/13 12:59:20.801 glacier2router: Network: listening for tcp connections 
    at :::40686
       local interfaces: GLACIER_LOCAL_IP, 127.0.0.1, 0:0:0:0:0:0:0:1
    -- 06/04/13 12:59:20.802 glacier2router: Network: published endpoints for object
     adapter `Glacier2.Server':
       tcp -h GLACIER_LOCAL_IP -p 40686
    -- 06/04/13 12:59:20.802 glacier2router: Network: published endpoints for object
     adapter `Glacier2Internal.Verifiers':
    
    -- 06/04/13 12:59:20.803 glacier2router: Network: accepting tcp connections at :
    ::4063
    -- 06/04/13 12:59:20.804 glacier2router: Network: accepting tcp connections at :
    ::40686
    
    (at this point I try to connect with my IceTouch application)
    
    -- 06/04/13 12:59:31.290 glacier2router: Network: accepted tcp connection
       local address = ::ffff:GLACIER_LOCAL_IP:4063
       remote address = ::ffff:ICETOUCH_IP_ADDR:53429
    -- 06/04/13 12:59:31.290 glacier2router: Protocol: sending validate connection 
       message type = 3 (validate connection)
       compression status = 0 (not compressed; do not compress response, if any)
       message size = 14
    -- 06/04/13 12:59:31.358 glacier2router: Protocol: received request 
       message type = 0 (request)
       compression status = 0 (not compressed; do not compress response, if any)
       message size = 58
       request id = 1
       identity = Glacier2/router
       facet = 
       operation = getClientProxy
       mode = 1 (nonmutating)
       context = 
    -- 06/04/13 12:59:31.359 glacier2router: Network: closing tcp connection
       local address = ::ffff:GLACIER_LOCAL_IP:4063
       remote address = ::ffff:ICETOUCH_IP_ADDR:53429
    
    
  • benoit
    benoit Rennes, France
    Hi,

    It's not clear what the problem could be.

    From your client trace, the getClientProxy request indicates that the client is making a routed call on the router when doing the checkedCast. This shouldn't happen, calls on the router proxy shouldn't be routed. Somehow, it appears that your default router proxy has a router set and the fact that the getClientProxy call succeeds would imply that a session is already established.

    From the Glacier2 router trace, I only see a getClientProxy request which is being rejected, no ice_isA requests. This time it appears that the client checkedCast fails before being sent since we don't see ice_isA calls.

    It also looks like you're using another router proxy for setting up the object adapter (you call createObjectWithRouter with self.router).

    Are you creating multiple sessions to different routers using the same communicator? Is your client re-establishing sessions with the Glacier2 router? If it does re-establish the session, does it correctly destroys the previous session and communicator and re-establish the session with a brand new communicator?

    Could you could perhaps provide us with a small test-case the demonstrate the problem? Or could you provide the client code that configures the communicator and establishes the session? Also, can you provide traces from the same run for both the client and the Glacier2 router?

    Please enable the following properties in the client:
    Ice.Trace.Protocol=2
    Ice.Trace.Network=2
    Ice.Trace.Retry=1
    

    And in the Glacier2 router:
    Ice.Trace.Protocol=2
    Ice.Trace.Network=2
    Glacier2.Trace.Session=1
    Glacier2.Client.Trace.Reject=1
    

    Cheers,
    Benoit.
  • Thank you very much for your quick response. I think some of the problems were related to the execution of two request to the communicator in two different execution threads. Finally I could make the checked cast properly; I have other issues now, but at least this one has been solved. :o

    Thanks!