Archived

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

? about callback : NoEndpointException

hi , i'm using ice for a ivr project with cpp. I have got some confused problem.
I made a client object and a server object.when start the server and client ,client will registered a callback to server. When server use the callback to send event to
client, we got the NoEndPointException.
the exception's detail is from visual c++2003.
===============================
-__ex {...} const Ice::LocalException &
-IceUtil::Exception {_file=0x1015bb9c ".\Reference.cpp" _line=1109 } IceUtil::Exception
- __vfptr 0x10150d64 const Ice::NoEndpointException::`vftable' *
[0]0x10007810 Ice::NoEndpointException::`vector deleting destructor'(unsigned int) *
[1]0x10093160 Ice::NoEndpointException::ice_name(void) *
[2]0x100754a0 Ice::NoEndpointException::ice_print(std::basic_ostream<char,std::char_traits<char> > &) *
[3]0x100931c0 Ice::NoEndpointException::ice_clone(void) *
[4]0x10093250 Ice::NoEndpointException::ice_throw(void) *
-_file 0x1015bb9c ".\Reference.cpp" const char *
46 '.' const char
_line 1109 int
===================================

Thers is the callback interface:
interface CallbackRcv
{
int RcvSGEvent(Event event);
};
interface CallbackSender
{
void RegClient(CallbackRcv* proxy, Ice::Identity ident);
};
in the CallBackSerderI class, we copy proxy to a member variable m_CallbackProxy.
in other server side thread,which hold the pointer to the CallbackSenderI object, we call m_CallBackProxy.RcvEvent( _sEvent).
I used current.con->createProxy(ident) to get proxy,also. but we got the same problem.

Comments

  • matthew
    matthew NL, Canada
    From this description its hard to work out what the problem is. Did you look at the callback demo (demo/Ice/callback)? If that does not help please post a complete, compilable self-contained example that demonstrates the problem and we can try to help.
  • //============server code:VGProxyServer.cpp==================
    #include <iostream>
    #include <VGProxy.h>
    #include <Ice/Ice.h>
    #include <Ice/Identity.h>
    
    using namespace std;
    using namespace Service;
    using namespace Ice;
    
    class CallbackProxy
    {  
    public:
    	::Service::VGCallbackRcvPrx proxy1;
            ::Service::VGCallbackRcvPrx proxy2;
    	bool bInit;
    	CallbackProxy()	
    	{bInit = false;}
    };
    
    class CallBackSenderI:public Service::CallbackSender
    {
    public:
    	CallbackProxy m_CallbackProxy;
    public:
    	CallBackSenderI(void){}
    	virtual ~CallBackSenderI(void){}
    
    public: 
    	virtual void RegClient(const Service::VGCallbackRcvPrx & proxy, const ::Ice::Identity& ident, const ::Ice::Current& current=::Ice::Current());
    };
    
    void CallBackSenderI::RegClient(const Service::VGCallbackRcvPrx & proxy, const ::Ice::Identity& ident, const ::Ice::Current& current)
    {
    	cout << "initiating callback" << endl;
            m_CallbackProxy.bInit =true;
    	[COLOR="Red"]m_CallbackProxy.proxy1 = proxy;
    
    	m_CallbackProxy.proxy2 = VGCallbackRcvPrx::uncheckedCast(current.con->createProxy(ident));[/COLOR]
    
    
    
    }
    class testThread : public IceUtil::Thread
    {
    	CallBackSenderI* m_psender;
    public:
    	testThread(void):m_psender(NULL),bIsOne(false)
    	{
    	};
    	testThread(CallBackSenderI* pSender,bool bOne):m_psender(pSender),bIsOne(bOne)
    	{	
    	};
    	virtual ~testThread(void)
    	{
    	};
    	virtual void run()
    	{
    		if (bIsOne == true)
    			run1();
    		else if (bIsOne == false)
    			run0();
    	};
    	void run1()
    	{
    		while(true)
    		{
    			Service::SGEvent _sEvent;
    			IceUtil::Mutex::Lock _lock(bMutex);
    			if (m_psender->m_CallbackProxy.bInit && bSwitch)
    			{
    [COLOR="Yellow"]m_psender->m_CallbackProxy.proxy*->RcvSGEvent(_sEvent);[/COLOR]
    			}
    		}
    	}
    
    	void run0()
    	{
    		do
    		{
    		cout << "s for start other to stop " << endl;
    		cout << "int:";
    		char c;
    		cin >> c ;
    		IceUtil::Mutex::Lock _lock(bMutex);
    		if (c == 's')
    			bSwitch = true;
    		else
    			bSwitch = false;
    		cout << endl;
    		}while(true);
    
    	}
    	static bool bSwitch;
    
    private:
    	bool bIsOne;
    	::IceUtil::Mutex bMutex;
    
    };
    
    bool testThread::bSwitch = false;
    class VGProxyServer :public Ice::Application
    {
    public:
    	VGProxyServer(void){};
    	virtual ~VGProxyServer(void){};
    
    	virtual int run(int argc, char** argv);
    };
    
    int main(int argc, char* argv[])
    {
    	VGProxyServer app;
    	return app.main(argc,argv,"vgproxy.server");	
    }
    
    int VGProxyServer::run(int argc, char** argv)
    {
    	CallBackSenderI* sender = new CallBackSenderI;
    	Ice::ObjectAdapterPtr adapter = communicator()->createObjectAdapter("VGProxyServer");
    	adapter->add(sender, communicator()->stringToIdentity("CallBackSender"));
        adapter->activate();
    
    	testThread* thread1 = new testThread(sender,true);
    	testThread* thread = new testThread(sender,false);
    
    	thread->start();
    	thread1->start();
    
        communicator()->waitForShutdown();
        return EXIT_SUCCESS;
    }
    
  • //============client code:client.cpp===================
    #include <Ice/application.h>
    #include <IceUtil/UUID.h>
    #include <VGProxy.h>
    #include <map>
    
    using namespace std;
    using namespace Ice;
    using namespace Service;
    
    class VGCallbackRcvI : public Service::VGCallbackRcv
    {
    public:
    	virtual ::Ice::Int RcvSGEvent(const Service::SGEvent& event, const ::Ice::Current& current = ::Ice::Current());
    
    };
    
    ::Ice::Int VGCallbackRcvI::RcvSGEvent(const Service::SGEvent& event, const ::Ice::Current& current )
    {
    	cout << "received callback." << event.EventID << endl;
    	return 0;
    }
    
    class VGProxyClient : public Ice::Application
    {
    public:
    	VGProxyClient(void):m_pCallBackReceiver(NULL){}
    	virtual ~VGProxyClient(void){}
    
    	CallbackSenderPrx m_twowayCallbackSender;
    	VGCallbackRcvI* m_pCallBackReceiver;
    
    	virtual int run(int argc, char* argv[]);
    };
    
    int VGProxyClient::run(int argc, char* argv[])
    {	
    		Ice::PropertiesPtr properties = communicator()->getProperties();
    
    		::std::string proxy = properties->getProperty("CallBackSender.Proxy");
    
    		Ice::ObjectAdapterPtr adapter = communicator()->createObjectAdapter("Callback.Client");
    		m_pCallBackReceiver = new VGCallbackRcvI;
    
    		m_twowayCallbackSender = CallbackSenderPrx::checkedCast(
    		communicator()->stringToProxy(proxy)->ice_twoway()->ice_timeout(-1)->ice_secure(false));
    		Ice::Identity ident;
    		ident.name = IceUtil::generateUUID();
    		ident.category = "";
    		adapter->add(m_pCallBackReceiver, ident);
    		adapter->activate();
    
    		VGCallbackRcvPrx twowayR = VGCallbackRcvPrx::uncheckedCast(
    			adapter->createProxy(communicator()->stringToIdentity("callbackReceiver")));
    
    m_twowayCallbackSender->ice_getConnection()->setAdapter(adapter);
    		[COLOR="Red"]m_twowayCallbackSender->RegClient(twowayR, ident);[/COLOR]
    
    		communicator()->waitForShutdown();
    
        return 0;
    }
    
    
    int main(int argc, char* argv[])
    {
    	VGProxyClient g_app;
    	g_app.main(argc,argv,"vgproxy.client");
    	return 0;
    }
    
  • //============ice file : VGProxy.ice====================
    #include <Ice/Identity.ice>
    module Service
    {
    struct SGEvent
    {
    short EventID;
    short ResID;
    };
    interface VGCallbackRcv
    {
    int RcvSGEvent(SGEvent event);
    };
    interface CallbackSender
    {
    void RegClient(VGCallbackRcv* proxy, Ice::Identity ident);
    };
    };
    //============================

    i have wrote lots of code, so it spent me some time to reduce code to this demo.
    there is a other device worked with the server object in my project.
    i made a thread get user input give server event,just like the device.

    the client side program is controlled by a node. In my project server will get the node load, but in this demo, node is nothing for server and client.

    //=============================
    zhere are two proxies for callbackreciver.one is get from the interface CallBackSenderI::RegClient(const Service::VGCallbackRcvPrx & proxy, const ::Ice::Identity& ident, const ::Ice::Current& current)

    other is get from current.con->createProxy();
    when i use the first proxy, i get NoEndPoint exception
    for seconde , i get Connectiontimeout exception sometimes.
  • marc
    marc Florida
    VGCallbackRcvPrx proxy2 = VGCallbackRcvPrx::uncheckedCast(current.adapter->createProxy(ident));
    VGCallbackRcvPrx proxy1 = VGCallbackRcvPrx::uncheckedCast(current.con->createProxy(ident));
    

    The first line doesn't make sense in this context. It would not create a proxy that points to the client for the callback, but it would point to the server. As for why you get a "no endpoints" exception, this would normally mean that you didn't configure any endpoints for the object adapter. However, since you can receive requests, this cannot be the case. Or perhaps you override the published endpoints for the object adapter? On the other hand, your code is broken in that you don't do proper mutex protection for writing to m_CallbackProxy, so all bets are off.

    The second line creates a fixed proxy for bi-directional connections. No endpoints are required, since it uses the existing incoming connection. As for why you get a timeout exception sometimes, I can only speculate without further information. It might be possible that you get this exception because your client is currently invoking an operation on the server, or busy dispatching a different callback. In both cases it helps to increase the size of the client size thread pool, e.g., Ice.ThreadPool.Client.Size=5.

    If you would like us to further look into this problem, please further reduce your example by removing everything unrelated to the exception, make your application thread-safe, post it in a readable format (use [code] tags), and supply your configuration. You should also make sure to not use regular pointers such as "CallBackSenderI* pSender" but instead use smartpointers like "CallBackSenderIPtr pSender" (please see the Ice manual for how to define smart pointers for your servant classes).
  • there are the config files.
    vgproxy.server
    VGProxyServer.Endpoints=default -p 10000
    
    vgproxy.client
    CallBackSender.Proxy=CallBackSender:default -p 10000
    


    void CallBackSenderI::RegClient(const Service::VGCallbackRcvPrx & proxy, const ::Ice::Identity& ident, const ::Ice::Current& current)
    {
    	cout << "initiating callback" << endl;
            m_CallbackProxy.bInit =true;
    	m_CallbackProxy.proxy1 = proxy;
    	m_CallbackProxy.proxy2 = VGCallbackRcvPrx::uncheckedCast(current.con->createProxy(ident));
    }
    

    when i use m_CallbackProxy.proxy1 to callback i will get no endpoint exception.
    when i use m_CallbackProxy.proxy2 to callback, if the time between callback invoking is more zhan 15s, zhen got connection timeout exception.
  • matthew
    matthew NL, Canada
    I think Marc explained why you are getting these exceptions. If you want us to look into this problem further you must post a complete minimal self-contained and compilable example in a suitable format (like a .zip file).
  • thank you,maybe my explanation is not very clear. please have some time on my little project.
  • marc
    marc Florida
    You have now modified the code as follows:
    m_CallbackProxy.proxy1 = proxy;
    m_CallbackProxy.proxy2 = VGCallbackRcvPrx::uncheckedCast(current.con->createProxy(ident));
    

    With the first line, you get a NoEndpointsException because your client doesn't have any endpoints configured.

    With the second line, you correctly set up a proxy for bi-directional use. However, note that you do not set m_CallbackProxy.proxy1 in a thread-safe manner. In any case, I do not believe that this is the problem. Do you perhaps have active connection management enabled, so that the connection is closed? What do you get if you trace the server with --Ice.Trace.Network=3 and --Ice.Trace.Protocol=1?
  • thank you marc.

    for the configuration yes zhere is "Ice.ACM.Server=10" setted. now i have know about second line problem. and i couldn't configu client endpoint in fact, because the client was controled by the node of icegrid, so i don't know port of client adapter.

    now i store the proxy string which make up with identity and endpoint gotten from node info.

    i think i should read the manual more.

    thank you again!
    :D