Nested Invocations

3 min read

3 min read

3 min read

3 min read

3 min read

3 min read

3 min read

3 min read

3 min read

A nested invocation is one that is made within the context of another Ice operation. For instance, the implementation of an operation in a servant might want to invoke an operation another object (using a proxy).

Making a nested invocation is legitimate, even common, however you need be careful to avoid deadlocks.

The general rule to avoid deadlocks is do not hold onto any shared resource while waiting.

If you make a synchronous two-way invocation, you’re waiting: your thread is blocked until it gets the response from the target Ice object. And if you make this synchronous invocation within a synchronous dispatch, you’re holding onto a shared resource: the dispatch thread (current thread) from an Ice thread pool.

The client calls opA on Server A, which calls opB on Server B. Server B attempts a callback to Server A, but Server A cannot dispatch it while its thread is blocked in the nested invocation.

Nested invocation deadlock.

In this diagram, we assume all calls are synchronous and both Server A and Server B use the default configuration, with a single thread in their respective server thread pools. We get a deadlock because Server A’s thread pool is exhausted (its only thread is waiting for the opB invocation to complete).

Making the shared resource more abundant (e.g., by configuring more threads in your Ice thread pool) can work for a while, but is brittle. The correct solution is to follow the shared resource rule (see above) and make an asynchronous invocation instead of a synchronous one from the dispatch thread. Or alternatively, dispatch asynchronously (with AMD) and make the synchronous invocation from a separate thread - not an Ice thread pool thread.