Archived

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

Deleting proxies and object from an adapter?

I was wondering what would be the correct method for deleting proxies and objects from an adapter? For example, should I delete the proxy first and then remove the object from the adapter and then delete it. Is there a condition that I need to wait on before proceeding with the delete.

If I delete a proxy in an Ice server and a client has already issued a method or is about to should I get an Ice exception in the client?

Possibly related, I'm seeing some cases where an ice_ping from the client on the proxy is not returning. We are using ice_ping as a test for whether the object is alive, but it doesn't return and there is no exception so our program hangs. Would you have any ideas on what we might be doing wrong and how to fix it? This occurs when we are deleting proxies and objects.

Last and not sure if this is helpful or not, but the other detail I have is that this is a callback scenario. The client is a server and the server is a client. So in the example above the proxy was created by app1 and then sent to app2. App2 is trying to use the proxy created by app1 and app1 is trying to delete the proxy and the object when deadlock occurs in app2 waiting on socket select in Ice.

Regards --Roland

Comments

  • Re: Deleting proxies and object from an adapter?
    Originally posted by rhochmuth
    I was wondering what would be the correct method for deleting proxies and objects from an adapter? For example, should I delete the proxy first and then remove the object from the adapter and then delete it. Is there a condition that I need to wait on before proceeding with the delete.

    Deleting a proxy has nothing to do with removing a servant from the object adapter. The two are unrelated, and you can do this in any order you like.

    If you remove a servant from an object adapter, but still have a proxy to the Ice object implemented by such servant, and you invoke on that proxy, then you will get an "object not exist" exception.
    Originally posted by rhochmuth
    If I delete a proxy in an Ice server and a client has already issued a method or is about to should I get an Ice exception in the client?

    Deleting a proxy doesn't do anything to the Ice object. It only destroys the proxy, nothing more. The lifecycle of proxies is completely independent of the lifecycle of servants.
    Originally posted by rhochmuth

    Possibly related, I'm seeing some cases where an ice_ping from the client on the proxy is not returning. We are using ice_ping as a test for whether the object is alive, but it doesn't return and there is no exception so our program hangs. Would you have any ideas on what we might be doing wrong and how to fix it? This occurs when we are deleting proxies and objects.

    Last and not sure if this is helpful or not, but the other detail I have is that this is a callback scenario. The client is a server and the server is a client. So in the example above the proxy was created by app1 and then sent to app2. App2 is trying to use the proxy created by app1 and app1 is trying to delete the proxy and the object when deadlock occurs in app2 waiting on socket select in Ice.

    Regards --Roland

    It is possible that your application runs out of threads to handle the callback for the ice_ping. To find out what's going on, it might be helpful to set this property:

    Ice.ThreadPool.Server.SizeWarn

    With this property, you will get warnings if you run low on threads. Here is an example:

    # Initial and minimum number of threads
    Ice.ThreadPool.Server.Size=10

    # Maximum number of threads
    Ice.ThreadPool.Server.SizeMax=50

    # Print a warning if 40 or more threads are used
    Ice.ThreadPool.Server.SizeWarn=40
  • Hi Marc, Thanks again for the reply. I could have more issues in my code or improper use of Ice. I'm not sure we were seeing the "object not found" exception when we removed the servant from the adapter. I'll have to re-verify this. We had a few other issues in our application, like deadlock, that I guess could have prevented the ice_ping from returning since all Ice threads might have been waiting on a resource. If I understand correctly from you previous post, if all your Ice threads are used and in deadlock then ice_ping will not return. OK, that makes sense.

    What I did was create a separate object adapter for each client/server connection. Instead of relying on an "object not found" exception I rely on "connect lost/closed" exception. This seems to work, but I don't know why.

    So now that I have an object adapter for each client/server connection, when disconnecting I just

    disconnect()
    {
    adapter->deactivate();
    delete proxy;
    delete object;
    }

    This seems to work great! When the adapter is deactivated the client gets an exception. Do I need adapter->waitForShutdown()?

    What would happen if I just

    disconnect()
    {
    delete proxy;
    delete object;
    }

    and the client was in the middle of transmitting a long oneway request. Is it possible that I was deleting the object while an Ice thread was in the process of using it? This was how I had our application structured, and I don't believe that the client was getting an "object not found" exception in this case.

    So basically, almost the same code. In one case I have a separate adapter for each client/server connection, this works, and in the other case all client/server connections share the same object adapter.

    Regards --Roland
  • Originally posted by rhochmuth
    What I did was create a separate object adapter for each client/server connection. Instead of relying on an "object not found" exception I rely on "connect lost/closed" exception. This seems to work, but I don't know why.

    Hmm... this sounds rather inefficient. It means that you open and listen on a port for each Ice object.

    Also note that reachability of an Ice object is conceptually not the same as its existence. This might not matter for you application at this point, but it will prevent you from using features such as active connection management.
    Originally posted by rhochmuth
    So now that I have an object adapter for each client/server connection, when disconnecting I just

    disconnect()
    {
    adapter->deactivate();
    delete proxy;
    delete object;
    }

    What do you exactly mean with "delete"? Of course you must not call the C++ operator delete, neither on a proxy nor on a servant. Both are reference counted, meaning that all you have to do is to drop the last Prx or Ptr, then the proxy or servant will automatically be deleted.
    Originally posted by rhochmuth
    This seems to work great! When the adapter is deactivated the client gets an exception. Do I need adapter->waitForShutdown()?

    You mean waitForDeactivate()? Since deactivate() is not immediate, and your applicaton seems to depend on completion of deactivation, you should call waitForDeactivate() after calling deactivate().
    Originally posted by rhochmuth
    What would happen if I just

    disconnect()
    {
    delete proxy;
    delete object;
    }

    and the client was in the middle of transmitting a long oneway request. Is it possible that I was deleting the object while an Ice thread was in the process of using it? This was how I had our application structured, and I don't believe that the client was getting an "object not found" exception in this case.

    Again, I don't know what you mean with "delete". Servants are reference counted, so as long as the servant is still registered with the object adapter, it will not be deleted.

    Same applies to the proxy, proxies are reference counted, too. And the lifecycle of proxies is independent of the lifecycle of the servant implementing an Ice object, so what you do to the proxy doesn't matter.
  • Sorry, I wasn't too clear.

    1. I don't create a separate object adapter for each object. I create a separate object adapter for each client/server session. So if if I have client1, client2, ..., clientN, I create adapter1, adapter2, ...., adapterN on the server. Each object adapter has many objects within it.

    2. Your right, I don't actually delete a proxy. My code is as follows:

    class ObjectProxyContainer
    {
    public:
    ObjectProxyContainer(Ice::ObjectAdapterPtr adapter);

    FooImp *fooImpl;
    FooPrx foo;
    ...
    };

    ObjectProxyContainer just creates all my proxies. I have code that sort of looks like this

    ObjectProxyContainer::ObjectProxyContainer(Ice::ObjectAdapterPtr adapter)
    {
    // Create FooImpl and add to adapter
    fooImpl = new FooImpl();
    adapter->add(fooImpl, id);
    fooPrx = FooPrx::uncheckedCast(...);
    };

    connect()
    {
    // Create object adapter and activate
    adapter = ...;
    adapter->activate();

    // Create objects and proxies
    objectProxyContainer = new ObjectProxyContainer(adapter);
    }

    disconnect()
    {
    adapter->deactivate();

    delete objectProxyContainer;
    }

    I hope I got all this more or less accurate this time. The only difference in my code before and after the change is that in this case I create a new object adapter for each connect(). In my code before, I created a single object adapter that was used on all connect/disconnects as follows:

    connect()
    {
    // Create objects and proxies
    objectProxyContainer = new ObjectProxyContainer(adapter);
    }

    disconnect()
    {
    delete objectProxyContainer;
    }
  • In the 2nd version of your code, if you do not deactivate the object adapter, you must remove the servant from the object adapter if you don't want the servant to receive any further requests. For example:

    adapter->remove(id);

    Then new requests will cause an "object not exist" exception. Requests that are in progress when calling remove() will complete as usual.

    You should never call delete on fooImpl. It is reference counted, and will be deleted automatically when the last reference to it is destroyed. In your case, this will happen during or after the remove() call. (I.e., when remove() returns, *and* all outstanding requests have completed.)

    I recommend to study the chapter about the object adapter in the Ice manual, which explains this in detail.