Archived

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

Invoking oneway with AMI blocks

Hi Folks,

I am developing multi-threaded application with Ice Embedded 1.3.0. I am using AMI to invoke oneway callback function. If the remote process where callback is implemented goes down (killed) then it seams like the asynchronous invocation gets blocked forever in __acquireCallback() call.

Here is the where it happens in generated code:
vehicle::AMI_StreamReceiver_nextChunk::__invoke(const ::vehicle::StreamReceiverPrx& __prx, const ::vehicle::ByteSeq& chunk, const ::Ice::Context* __ctx)
{
    __acquireCallback(__prx);  <<<<< blocks here

Since I am also managing my own threads and doing synchronization, I am not 100% sure if it is my problem or ICE.

That is why I would like to ask whether it is expected behavior of such AMI invocation or it is a sign that the error is in my code?

I've seen that __acquireCallback() function wait() without timeout for __monitor object. So if it is really the root of the problem in my scenario, I am wondering what might be the solution for this problem? Would it make sense for the future versions of Ice to extend AMI interface with timeout value for such cases?

BTW, as I understand, IceE uses the "old" AMI interface in contrast to the new one available in Ice (not embedded). Are there any plans to move IceE to the new interface also?

Thank you very much,

Comments

  • benoit
    benoit Rennes, France
    Hi,

    An AMI invocation blocks here if the AMI callback object is already "in-use" by another AMI invocation. For example, with the following code where 2 invocations are using the same AMI callback object:
       AMI_Hello_sayHelloPtr cb = new AMIHelloCallbackI();
       proxy->sayHello_async(cb);
       proxy->sayHello_async(cb);
    

    The second sayHello invocation will hang until the response for the first invocation has been received. The following code will allow the 2 AMI calls to be sent concurrently:
       AMI_Hello_sayHelloPtr cb1 = new AMIHelloCallbackI();
       proxy->sayHello_async(cb1);
       AMI_Hello_sayHelloPtr cb2 = new AMIHelloCallbackI();
       proxy->sayHello_async(cb2);
    


    So my guess with your application is that an AMI call hangs because the server is killed and subsequent AMI calls which are using the same callback also hang the calling thread as a result. I recommend to:
    • Use connection timeouts to ensure calls don't hang for too long in case a server terminates ungracefully.
    • Use separate callback objects to allow AMI invocations to be sent concurrently.

    We didn't decided yet whether or not we will port the new AMI mapping to Ice-E.

    Cheers,
    Benoit.
  • Hi Benoit,
    benoit wrote: »
    An AMI invocation blocks here if the AMI callback object is already "in-use" by another AMI invocation.

    This is exactly the case I have! My callbacks are stateless and basically just updating some statistic. So I thought it is not necessary to permanently create new objects on the heap. Now when you are saying it, I get remember that I've read somewhere in the documentation that different callback objects must be used.

    So I think I should fix my code. Is it possible to "re-use" AMI callbacks which was already called back? I am thinking about creating pool of callback objects to avoid permanent creation/deletion of them (I am on embedded system and worry about performance and memory fragmentation issues).

    Thank you very much for pointing the problem out!

    Regards,
  • benoit
    benoit Rennes, France
    Yes, re-using a callback whose response has been received (either ice_exception or ice_response was called on it) is fine.

    Cheers,
    Benoit.