Archived

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

Blocked by nested callback

I've written a simple ICE app based on chatroom callback example of Connection#1, and easily come across with nested callback situation
the belwo is code snippet:-

========================================================
Code in servant ControlSession receive callback object:-

public class ControlSessionImpl extends _ControlSessionDisp {

private ControlRoom ctlroom;
private CreaturePrx client;

public void setCreature(CreaturePrx creature, Current __current)
{
//creature is a callback onject
ObjectPrx roomPrx = __current.adapter.createProxy(Ice.Util.stringToIdentity("ControlRoom1"));
ControlRoomPrx ctlRoomPrx = ControlRoomPrxHelper.uncheckedCast(roomPrx);
System.out.println("Thread receiving request in setCreature()"+ Thread.currentThread().getName());
//set Proxy via client's callback object
creature.enter(ctlRoomPrx);

}

....

Code in client callbackobject Creature

public class CreatureImpl extends _CreatureDisp {

....the below is code being called by server
public void enter(RoomPrx location, Current __current)
{
System.out.println("Hello Roger came.....");
System.out.println("Room name:"+location.name()); // <
trying to call server again here, then client thread was blocked

if (location.ice_isA("::NIceCube::ControlRoom")){
if( (control_room = ControlRoomPrxHelper.checkedCast(location))!=null){
System.out.println(control_room.name());
}
}
System.out.println(location.ice_id());
}

.......
}
========================================================


ICE thread pool size is set as below, I think it should be enough:-

[exec] Ice.ThreadPool.Server.SizeMax=20
[exec] Ice.ThreadPool.Client.SizeMax=5

Some error log from server and glacier2:-
----ICE runtime report:-
[exec] warning: dispatch exception:
[exec] identity: a:1:8:3c:-717e6c27:10a91df39f6:-8000
[exec] facet:
[exec] operation: setCreature
[exec] Ice.UnknownLocalException
[exec] unknown = ".\ConnectionI.cpp:258: Ice::ForcedCloseConnectionException:
[exec] protocol error: connection forcefully closed"
[exec] at IceInternal.Outgoing.invoke(Outgoing.java:148)
[exec] at NIceCube._CreatureDelM.enter(_CreatureDelM.java:32)
[exec] at NIceCube.CreaturePrxHelper.enter(CreaturePrxHelper.java:32)
[exec] at NIceCube.CreaturePrxHelper.enter(CreaturePrxHelper.java:19)
[exec] at net.nicecube.model.ControlSessionImpl.setCreature(ControlSessionImpl.java:40)
[exec] at NIceCube._ControlSessionDisp.___setCreature(_ControlSessionDisp.java:130)
[exec] at NIceCube._ControlSessionDisp.__dispatch(_ControlSessionDisp.java:202)
[exec] at IceInternal.Incoming.invoke(Incoming.java:145)
[exec] at Ice.ConnectionI.invokeAll(ConnectionI.java:1951)
[exec] at Ice.ConnectionI.message(ConnectionI.java:1131)
[exec] at IceInternal.ThreadPool.run(ThreadPool.java:753)
[exec] at IceInternal.ThreadPool.access$100(ThreadPool.java:12)
[exec] at IceInternal.ThreadPool$EventHandlerThread.run(ThreadPool.java:1194)

Glacier2 Log
glacier2router: warning: dispatch exception: .\ConnectionI.cpp:258: Ice::ForcedCloseConnectionException:
protocol error: connection forcefully closed
identity: 5i&tp\'JT5W]mbH|0kd{L/callbackReceiver
facet:
operation: enter

BTW I din't try this program without glacier2 and use ICE 3.0.0 runtime

as far as I understand, if I set enough size to thread pool, the ICE should be able to handle reasonable nested call without deadlock.

Does anyone have suggestion?

Comments

  • benoit
    benoit Rennes, France
    Hi Roger,

    Did you apply any Glacier2 patches to your Ice 3.0.0 distribution or is this with a vanilla Ice 3.0.0 distribution? For instance, there's a known issue with nested callbacks and Ice 3.0.0 distributions with [thread=2165]this patch[/thread] applied.

    Also, this has nothing to do with your problem but I believe the call to ice_isA() in the code below is not necessary. The checkedCast() and checking for null is enough.
    if (location.ice_isA("::NIceCube::ControlRoom"))
    {
       if((control_room = ControlRoomPrxHelper.checkedCast(location))!=null)
       {
          System.out.println(control_room.name());
       }
    }
    

    Cheers,
    Benoit.
  • Benoit,

    there is no patch applied to the 3.0.0 runtime I used. I have tried 3.0.1 as well, it leads to same problem. And I also tried to bypass glacier2router with same logic and the nested calls were completed successfully, so I guess it's something to do with glacier2. The followings are ice configuration files for each layer. Any further suggestuion appreciated!


    Glacier2:-

    Glacier2.Client.Endpoints=tcp -p 10005
    Glacier2.Server.Endpoints=tcp -h 127.0.0.1
    Glacier2.SessionManager=ControlRoom1:tcp -h 127.0.0.1 -p 10001
    Glacier2.PermissionsVerifier=verifier:tcp -h 127.0.0.1 -p 10001
    Glacier2.SessionTimeout=30

    Server:-

    Cube.Server.Endpoints=tcp -h 127.0.0.1 -p 10001
    Ice.ThreadPool.Client.SizeMax=5
    Ice.ThreadPool.Server.SizeMax=20


    Client:-

    Ice.Default.Router=Glacier2/router:tcp -p 10005
    Cube.Client.Router=Glacier2/router:tcp -p 10005
    Cube.Client.Endpoints=
    Ice.ACM.Client=0
    Ice.MonitorConnections=60
    Ice.RetryIntervals=-1
  • matthew
    matthew NL, Canada
    The easiest way for us to help you fix this problem is if you post a complete self-contained buildable application plus instructions to duplicate the error that shows this problem.
  • Yes, you are right,

    Please have a look at my program within the attached zip file, it inlcudes a complete eclipse project, one ant build.xml file and a sequence diagram picturing the blocked scenario.

    Before getting your ant run, first you may have to modify the line in build.xml to reflect installation dir of your ICE
    <property name="ice.home" value="C:/Ice-3.0.1"/>

    My test env is jdk1.5 on XP with ice3.0.1 and execute the following cmd in order in separate console window

    1. ant runService
    2. ant runGlacier2
    3. ant runClient
  • benoit
    benoit Rennes, France
    Hi Roger,

    The problem comes from the concurrency model used by your client, you're using the thread per connection concurrency model. This concurrency model when used with a bi-directional connection doesn't allow twoway nested invocations (a nested invocation is an invocation made from another Ice operation).

    The reason is that the connection thread is busy dispatching the Ice invocation (the enter() method in your example) and therefore it's not available to read the reply from the twoway nested invocation.

    If you change your client configuration to use the thread pool concurrency model and bump the number of threads of the client thread pool it will work. For example:
      # Ice.ThreadPerConnection=1
      Ice.ThreadPool.Client.Size=5
    

    However, I suspect this won't be an option for you if you want to use IceSSL since it requires the thread per connection concurrency model so your only option is to not make any invocations from your client callback objects.

    Cheers,
    Benoit.
  • benoit,

    Thank you so much. it works!
  • Any plan to remove SSL limitation in ICE Java 3.1 when using Java 5

    Benoit,

    It seems that the limitation of ICE thread pool unable to use together with SSL in Java is caused by the underlying SSL interface of Java 1.4 not supporting non-blocking socket

    However, Java 5 has included a new class SSLEngine as a solution for the above issue, it's a transport-independent API and support any IO mechanism and threading models.

    Since Tiger has gained popularity recently, I think it will be a very nice feature if ICE thread pool can use SSL in Java 5
  • marc
    marc Florida
    If only Java had a preprocessor with #ifdef/#else/#endif :)
  • sounds like a feature impossible:o
  • Surprise to see ICE 3.1 support using SSL together with Thread Pool mode for Java 5. :) Thank very much for your efforts!!!