Please report new issues athttps://github.com/DOCGroup
This bug concerns the collocation strategy 'direct' optimization that is present in the orb, and affects any corba server process. The ImR "induces" the condition and prevents the shut-cut logic in the ORB code from working correctly. CROSS-REFERENCE: Bugs 133, 1495, 1496. SYNOPSIS: Consider an application involing a Server and a Client, and consider that the client makes a request on a server object, which in turn makes another request on another object collocated in the server: Without the ImR present, collocation direct works fine in the server. The TAO::Invocation_Adapter sees that the object is collocated and invokes request on servant. With the ImR present however, collocation direct does not appear to work in the server. Instead requests made on collocated object are treated as remote requests and the reactor thread which is handling the request on a collocated object resumes waiting_for_events() as if the collocation were turned off. In the case of a single threaded reactor, the same thread then handles the socket event and eventually the call is invoked on the servant. In the case of a thread-pool reactor, a second thread typically handles the second part of the call sequence involving invoking the request on the servant. DESCRIPTION: I have supplied the full test harness plus notes as attachments to this mail. The first note file make-output.txt shows the output from making the test harness application. The following description shows how to demonstrate the problem using the test harness. The test server asserts in the request on the secondary object, causing a core to be produced. By examining the stack we can determine if the collocation direct optimisation is working or not. The first test involves the scenario where the ImR is not used. Please refer to supplied file: test-sh-out2.txt, which shows how the server and client were started. The corresponding stack frame from the core dump is contained in file: stack-frame2.txt. From stack-frame2.txt, it can be seen that collocation direct optimisation is working fine. The second test involves the scenario where the ImR is being used. Please refer to supplied file: test-sh-out1.txt, which shows how the server and client were started. The corresponding stack frame from the core dump is contained in file: stack-frame1.txt. From stack-frame1.txt, it can be seen that collocation direct optimisation is not working. The reactor thread which is handling the request on a collocated object resumes waiting_for_events() as if the collocation were turned off. Since the reactor only consists of a single thread, the same thread eventually completes the call BUT it can be seen from the stack that the optimisation is not taking place. TEST HARNESS: Client.cc ========================== #include <MTestC.hh> #include <iostream> #include <fstream> CORBA::ORB_var orb; BTest_var b; void print_menu() { std::cout<<"Give:"<<std::endl; std::cout<<"\t1 for createChild"<<std::endl; std::cout<<"\t2 for findChild and"<<std::endl; std::cout<<"\t3 for exit"<<std::endl; } int main(int argc, char *argv[]) { orb = CORBA::ORB_init(argc, argv, "TAO"); std::ifstream iorfile("iorfile.ior"); char ior[500]; iorfile>>ior; std::cout<<"ior ="<<ior<<std::endl; CORBA::Object_var obj = orb->string_to_object(ior); b = BTest::_narrow(obj.in()); try { b->test(); } catch(CORBA::SystemException &exc) { std::cout<<exc<<std::endl; } orb->destroy(); } MTest.idl ========================== #ifndef MTest_idl #define MTest_idl interface ATest { void test(); }; interface BTest { void test(); }; #endif MTest_i.cc ========================== #include <MTest_i.hh> #include <iostream> #include <fstream> #include <assert.h> //============================================================== BTest_i::BTest_i() : a_(ATest::_nil()) { PortableServer::ObjectId_var oidb = PortableServer::string_to_ObjectId("BTest"); // activate object g_poa->activate_object_with_id(oidb.in(), this); // obtain pointer to object CORBA::Object_var objVar = g_poa->id_to_reference(oidb.in()); // stringify IOR CORBA::String_var ior = g_orb->object_to_string(objVar.in()); std::ofstream iorfile("iorfile.ior"); iorfile<<ior.in()<<std::ends; iorfile.close(); // create A ATest_i *child = new ATest_i(); PortableServer::ObjectId_var oida = PortableServer::string_to_ObjectId("ATest"); g_poa->activate_object_with_id(oida.in(), child); CORBA::Object_var objAVar = g_poa->id_to_reference(oida.in()); a_ = ATest::_narrow(objAVar.in()); this->_remove_ref(); child->_remove_ref(); } BTest_i::~BTest_i() { std::cout << "destructor of BTest_i::~BTest_i" <<std::endl; } void BTest_i::test() throw(CORBA::SystemException) { a_->test(); } //============================================================== ATest_i::ATest_i() { } ATest_i::~ATest_i() { std::cout<<"Destructor of ATest_i::~ATest_i"<<std::endl; } void ATest_i::test() throw(CORBA::SystemException) { assert(0); } MTest_i.hh ========================== #ifndef MTest_i_hh #define MTest_i_hh #include <MTestS.hh> extern CORBA::ORB_ptr g_orb; extern PortableServer::POA_ptr g_poa; class ATest_i : public virtual POA_ATest, public virtual PortableServer::RefCountServantBase { public: ATest_i(); virtual ~ATest_i(); virtual void test() throw(CORBA::SystemException); virtual PortableServer::POA_ptr _default_POA() { return PortableServer::POA::_duplicate(g_poa); } }; class BTest_i: public virtual POA_BTest, public virtual PortableServer::RefCountServantBase { public: BTest_i(); virtual ~BTest_i(); virtual void test() throw(CORBA::SystemException); virtual PortableServer::POA_ptr _default_POA() { return PortableServer::POA::_duplicate(g_poa); } private: ATest_var a_; }; #endif Makefile ========================== # # Makefile # # Revisions # --------- # 17/05/2004, gtsal, initial # first_target: all # force them to define this ############################## # Flags ############################## ORB_INCDIR = -I/tools/chameleon_tao_common/tao1.4.2/ACE_wrappers \ -I/tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO \ -I/tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/orbsvcs CCFLAGS= -W -Wall -Wpointer-arith -O3 -g -pipe -D_REENTRANT $(ORB_INCDIR) -I. -DACE_HAS_EXCEPTIONS -D__ACE_INLINE__ CFLAGS= -W -Wall -Wpointer-arith -O3 -g -pipe -D_REENTRANT -I. COMPILE.cc= g++ $(CCFLAGS) -c COMPILE.c= g++ $(CFLAGS) -c ORB_LDLIBS = -L$(TAO_ROOT)/tao -L$(ACE_ROOT)/lib \ -L$(TAO_ROOT)/orbsvcs/orbsvcs \ -lTAO_PortableServer -lTAO -lACE LDFLAGS= -Wl,-E -L. $(ORB_LDLIBS) LINK.cc= g++ $(CCFLAGS) $(CPPFLAGS) $(LDFLAGS) LINK.c= g++ $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) ######################################### # Implicit compile rules ######################################### IDL=/tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/TAO_IDL/tao_idl IDLFLAGS= -Ge 2 -Gp -Gd -GI -GIh _TE.hh -GIs _TE.cc -GIe _i -hc "C.hh" -ci "C.i" -si "S.i" -hs "S.hh" -cs "C.cc" -ss "S.cc" -Sc -I./ .SUFFIXES: .SUFFIXES: .cc .idl $(SUFFIXES) %C.o: %C.cc g++ $(CCFLAGS) -c $< %S.o: %S.cc g++ $(CCFLAGS) -c $< %.o: %.cc g++ $(CCFLAGS) -c $< .cc: echo $@ >> targets_not_built.dep %S.cc: %.idl $(IDL) $(IDLFLAGS) $< %C.cc: %.idl $(IDL) $(IDLFLAGS) $< %C.hh: %.idl $(IDL) $(IDLFLAGS) $< %S.hh: %.idl $(IDL) $(IDLFLAGS) $< ############################## # Configuration files ############################## ############################## # IDLs/Headers/Sources ############################## ALL_IDLS= MTest.idl HDRS= TESTSRV_SRCS= MTestS.cc MTest_i.cc Srv_Main.cc TESTIDL_SRCS= MTestC.cc TESTCLT_SRCS= Client.cc ALL_SRCS= $(TESTSRV_SRCS) $(TESTIDL_SRCS) $(TESTCLT_SRCS) ############################### # Intermediate objects ############################### TESTSRV_OBJS= ${TESTSRV_SRCS:.cc=.o} TESTIDL_OBJS= ${TESTIDL_SRCS:.cc=.o} TESTCLT_OBJS= ${TESTCLT_SRCS:.cc=.o} ALL_OBJS= $(TESTSRV_OBJS) $(TESTIDL_OBJS) $(TESTCLT_OBJS) ############################## # Target libraries/binaries ############################## LIB_BUILD=g++ -G -Wl,-h -Wl,$@ -o $@ IDLLIB= idlClt IDLLIB_F= lib$(IDLLIB).so LIBS= $(LIB_F) ALL_LIBS= $(LIBS) $(IDLLIB_F) SRV_BIN= server CLT_BIN= client ALL_BINS= $(SRV_BIN) $(CLT_BIN) ############################## _IDLDERIVED= ${ALL_IDLS:.idl=C.hh} ${ALL_IDLS:.idl=C.cc} ${ALL_IDLS:.idl=C.i}\ ${ALL_IDLS:.idl=S.hh} ${ALL_IDLS:.idl=S.cc} ${ALL_IDLS:.idl=S.i}\ ${ALL_IDLS:.idl=_TE.hh} ${ALL_IDLS:.idl=_TE.cc} CLEAN_RM= $(RM) $(ALL_OBJS) core DISTCLEAN_RM= $(RM) $(_IDLDERIVED) *~ ir.out .pure Makefile.dep targets_not_built.dep iorfile.ior MAKEDEPEND= $(CPP) $(CPPFLAGS) $? > Makefile.dep ############# Html doc ALL_LIB_IDLS=$(ALL_IDLS) ALL_LIB_HDRS=$(HDRS) ############################## # Target build rules ############################## $(LIB_F): $(LIB_OBJS) $(LIB_BUILD) $(LIB_OBJS) $(IDLLIB_F): $(TESTIDL_OBJS) $(LIB_BUILD) $(TESTIDL_OBJS) $(SRV_BIN): $(TESTSRV_OBJS) $(RM) $@ $(LINK.cc) $(TESTSRV_OBJS) -o $@ \ -l$(IDLLIB) -lTAO_CosNaming \ $(LDLIBS) || rm -f $@ $(CLT_BIN): $(TESTCLT_OBJS) $(RM) $@ $(LINK.cc) $(TESTCLT_OBJS) -o $@ \ -l$(IDLLIB) -lTAO_CosNaming $(LDLIBS) || rm -f $@ depend: $(ALL_SRCS) $(MAKEDEPEND) Makefile.dep: echo "# Makefile.dep has not been built yet!" > Makefile.dep cleandepend: $(RM) Makefile.dep ############################## # Standard Targets/Rules ############################## all: $(ALL_LIBS) $(ALL_BINS) init: inst-hdrs install: inst-hdrs inst-libs uninstall: uninst-hdrs uninst-libs inst-hdrs: $(HDRS) $(INST_HDRS) inst-libs: $(LIBS) $(INST_LIBS) depend: $(ALL_SRCS) $(MAKEDEPEND) clean: $(CLEAN_RM) distclean: clean $(DISTCLEAN_RM) $(ALL_LIBS) $(ALL_BINS) ############################## # Other targets ############################## ############################## # Dependencies ############################## include Makefile.dep Srv_Main.cc ========================== #include <MTest_i.hh> #include <iostream> using namespace std; CORBA::ORB_ptr g_orb; PortableServer::POA_ptr g_poa; int main(int argc, char *argv[]) { CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "TAO"); g_orb = orb.in(); CORBA::Object_var poa_object = orb->resolve_initial_references("RootPOA"); if(CORBA::is_nil(poa_object.in())) { std::cout<<"Unable to initialize the RootPOA object"<<std::endl; return 0; } PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(poa_object.in()); PortableServer::POAManager_var poaMgr = rootPOA->the_POAManager(); poaMgr->activate(); CORBA::PolicyList policies(3); policies.length(3); policies[0] = rootPOA->create_lifespan_policy(PortableServer::PERSISTENT); policies[1] = rootPOA->create_id_assignment_policy(PortableServer::USER_ID); policies[2] = rootPOA->create_request_processing_policy(PortableServer::USE_SERVANT_MANAGER); PortableServer::POA_var thePOA = rootPOA->create_POA("SRV", poaMgr.in(), policies); g_poa = thePOA.in(); // PortableServer::POAManager_var mgr = thePOA->the_POAManager(); // mgr->activate(); for (CORBA::ULong i=0; i<policies.length(); ++i) { CORBA::Policy_ptr policy = policies[i]; policy->destroy(); } new BTest_i(); try { ACE_Time_Value timeout = 10000; cerr << "wait for requests" << endl; orb->run(timeout); } catch(CORBA::SystemException &exc) { std::cout<<"A system exception caught: "<<exc<<std::endl; } orb->destroy(); return 0; } STACK FRAME WITHOUT THE ImR PRESENT (notice how collocation strategy direct optimisation takes effect) #0 0xfe959b1c in __sigprocmask () from /usr/lib/libthread.so.1 #1 0xfe94e554 in _resetsig () from /usr/lib/libthread.so.1 #2 0xfe94dc44 in _sigon () from /usr/lib/libthread.so.1 #3 0xfe950db8 in _thrp_kill () from /usr/lib/libthread.so.1 #4 0xfe9ca030 in raise () from /usr/lib/libc.so.1 #5 0xfe9b559c in abort () from /usr/lib/libc.so.1 #6 0xfe9b5840 in _assert () from /usr/lib/libc.so.1 #7 0x00020990 in ATest_i::test (this=0x7ee48) at MTest_i.cc:66 #8 0x0001c174 in _TAO_ATest_Direct_Proxy_Impl::test (servant=0x7ee48) at MTestS.cc:535 #9 0x0001bf08 in _TAO_ATest_Strategized_Proxy_Broker::dispatch (this=0x2, obj=0x7edb0, forward_obj={ptr_ = @0xffbecd68}, args=0xffbecf84, num_args=1, op=0x1c148 "\235ã¿\220Ò\006", op_len=4, strategy=TAO_CS_DIRECT_STRATEGY) at MTestS.cc:416 #10 0xfefc444c in TAO::Collocated_Invocation::invoke (this=0xffbecd60, cpb=0x37f7c, strat=TAO_CS_DIRECT_STRATEGY) at operation_details.i:34 #11 0xfefc206c in TAO::Invocation_Adapter::invoke_collocated_i ( this=0xffbecf88, stub=0x7ece8, details=@0xffbecec0, effective_target=@0xffbece48, strat=TAO_CS_DIRECT_STRATEGY) at Invocation_Adapter.cpp:166 #12 0xfefc1e5c in TAO::Invocation_Adapter::invoke_i (this=0xffbecf88, stub=0x7ece8, details=@0xffbecec0) at Invocation_Adapter.cpp:83 #13 0xfefc1d78 in TAO::Invocation_Adapter::invoke (this=0xffbecf88, ex_data=0x0, ex_count=0) at Invocation_Adapter.cpp:44 #14 0xff376250 in ATest::test (this=0x7eda8) at MTestC.cc:142 #15 0x0002060c in BTest_i::test (this=0x7eda8) at MTest_i.cc:49 #16 0x0001d548 in POA_BTest::test_skel (_tao_server_request=@0xffbed568, _tao_servant=0x66000, _tao_servant_upcall=0x1) at MTestS.cc:1446 #17 0xff2de8dc in TAO_ServantBase::synchronous_upcall_dispatch (this=0x66008, req=@0xffbed568, servant_upcall=0x1d4c0, derived_this=0x66000) at Servant_Base.cpp:233 #18 0x0001da34 in POA_BTest::_dispatch (this=0x66000, req=@0xffbedb38, servant_upcall=0x1d4c0) at MTestS.cc:1690 #19 0xff29bd28 in TAO_Object_Adapter::dispatch_servant (this=0x0, key=@0xffbed568, req=@0xffbed568, forward_to={ptr_ = @0xffbed558}) at Object_Adapter.i:180 #20 0xff29c9dc in TAO_Object_Adapter::dispatch (this=0x62dc0, key=@0xffbed5d4, request=@0xffbed568, forward_to={ptr_ = @0xffbed558}) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/tao/Pseudo_VarOut_T.inl:131 #21 0xff02989c in TAO_Adapter_Registry::dispatch (this=0x51b6c, key=@0xffbed5d4, request=@0xffbed568, forward_to={ptr_ = @0xffbed558}) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/tao/Pseudo_VarOut_T.inl:131 #22 0xff042fcc in TAO_Request_Dispatcher::dispatch (this=<incomplete type>, orb_core=0x519e0, request=@0xffbed568, forward_to={ptr_ = @0x519e0}) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/tao/Tagged_Profile.i:23 #23 0xff06aa08 in TAO_GIOP_Message_Base::process_request (this=0x7ee90, transport=0x63ff0, cdr=@0xffbed6e8, output=@0xffbed720, parser=0x7eeb8) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/tao/Object.i:64 #24 0xff06a4f8 in TAO_GIOP_Message_Base::process_request_message ( this=0x7ee90, transport=0x63ff0, qd=0x0) at GIOP_Message_Base.cpp:700 #25 0xff04ae1c in TAO_Transport::process_parsed_messages (this=0xff06a2fc, qd=0xffbeda88, rh=@0x7ee90) at Transport.cpp:1810 #26 0xff049e6c in TAO_Transport::handle_input (this=0x63ff0, rh=@0xffbedf70, max_wait_time=0x0) at Transport.cpp:1282 #27 0xff050bc0 in TAO_Connection_Handler::handle_input_eh (this=0x7e9ac, h=9, eh=0x7e910) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/tao/Connection_Handler.inl:19 #28 0xff061fd0 in TAO_IIOP_Connection_Handler::handle_input (this=0x7e910, h=9) at IIOP_Connection_Handler.cpp:168 #29 0xfed8d694 in ACE_TP_Reactor::dispatch_socket_event (this=0x60f18, dispatch_info=@0x1) at TP_Reactor.cpp:657 #30 0xfed8cfb0 in ACE_TP_Reactor::handle_socket_events (this=0x60f18, event_count=@0xffbee164, guard=@0x1) at TP_Reactor.cpp:499 #31 0xfed8cc64 in ACE_TP_Reactor::dispatch_i (this=0x60f18, max_wait_time=0xffbee164, guard=@0xffbee1d8) at TP_Reactor.cpp:266 #32 0xfed8caac in ACE_TP_Reactor::handle_events (this=0x60f18, max_wait_time=0xffbee350) at TP_Reactor.cpp:171 #33 0xfed892e8 in ACE_Reactor::handle_events (this=0x60f18, max_wait_time=0xffbee350) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/ace/Reactor.inl:166 #34 0xfeff8eb4 in TAO_ORB_Core::run (this=0x519e0, tv=0xffbee350, perform_work=0) at ORB_Core.cpp:1893 #35 0x00021018 in main (argc=2, argv=0xffbee350) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/tao/Pseudo_VarOut_T.inl:58 STACK FRAME WIT THE ImR PRESENT (Notice that optimization is absent and request is treated as a remote call) #0 0xfe459b1c in __sigprocmask () from /usr/lib/libthread.so.1 #1 0xfe44e554 in _resetsig () from /usr/lib/libthread.so.1 #2 0xfe44dc44 in _sigon () from /usr/lib/libthread.so.1 #3 0xfe450db8 in _thrp_kill () from /usr/lib/libthread.so.1 #4 0xfe0ca030 in raise () from /usr/lib/libc.so.1 #5 0xfe0b559c in abort () from /usr/lib/libc.so.1 #6 0xfe0b5840 in _assert () from /usr/lib/libc.so.1 #7 0x00023064 in ATest_i::test (this=0x83e38) at MTest_i.cc:66 #8 0x0001e6d8 in POA_ATest::test_skel (_tao_server_request=@0xffbeba58, _tao_servant=0x83e38, _tao_servant_upcall=0x1) at MTestS.cc:617 #9 0xfe8de8dc in TAO_ServantBase::synchronous_upcall_dispatch (this=0x83e3c, req=@0xffbeba58, servant_upcall=0x1e650, derived_this=0x83e38) at Servant_Base.cpp:233 #10 0x0001ebc4 in POA_ATest::_dispatch (this=0x83e38, req=@0xffbec028, servant_upcall=0x1e650) at MTestS.cc:861 #11 0xfe89bd28 in TAO_Object_Adapter::dispatch_servant (this=0x0, key=@0xffbeba58, req=@0xffbeba58, forward_to={ptr_ = @0xffbeba48}) at Object_Adapter.i:180 #12 0xfe89c9dc in TAO_Object_Adapter::dispatch (this=0x6d680, key=@0xffbebac4, request=@0xffbeba58, forward_to={ptr_ = @0xffbeba48}) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/tao/Pseudo_VarOut_T.inl:131 #13 0xfe62989c in TAO_Adapter_Registry::dispatch (this=0x5c314, key=@0xffbebac4, request=@0xffbeba58, forward_to={ptr_ = @0xffbeba48}) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/tao/Pseudo_VarOut_T.inl:131 #14 0xfe642fcc in TAO_Request_Dispatcher::dispatch (this=<incomplete type>, orb_core=0x5c188, request=@0xffbeba58, forward_to={ptr_ = @0x5c188}) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/tao/Tagged_Profile.i:23 #15 0xfe66aa08 in TAO_GIOP_Message_Base::process_request (this=0x95258, transport=0x95020, cdr=@0xffbebbd8, output=@0xffbebc10, parser=0x95280) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/tao/Object.i:64 #16 0xfe66a4f8 in TAO_GIOP_Message_Base::process_request_message ( this=0x95258, transport=0x95020, qd=0x0) at GIOP_Message_Base.cpp:700 #17 0xfe64ae1c in TAO_Transport::process_parsed_messages (this=0xfe66a2fc, qd=0xffbebf78, rh=@0x95258) at Transport.cpp:1810 #18 0xfe649e6c in TAO_Transport::handle_input (this=0x95020, rh=@0xffbec460, max_wait_time=0x0) at Transport.cpp:1282 #19 0xfe650bc0 in TAO_Connection_Handler::handle_input_eh (this=0x94fa4, h=12, eh=0x94f08) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/tao/Connection_Handler.inl:19 #20 0xfe661fd0 in TAO_IIOP_Connection_Handler::handle_input (this=0x94f08, h=12) at IIOP_Connection_Handler.cpp:168 #21 0xfe38d694 in ACE_TP_Reactor::dispatch_socket_event (this=0x6be18, dispatch_info=@0x1) at TP_Reactor.cpp:657 #22 0xfe38cfb0 in ACE_TP_Reactor::handle_socket_events (this=0x6be18, event_count=@0xffbec654, guard=@0x1) at TP_Reactor.cpp:499 #23 0xfe38cc64 in ACE_TP_Reactor::dispatch_i (this=0x6be18, max_wait_time=0xffbec654, guard=@0xffbec6c8) at TP_Reactor.cpp:266 #24 0xfe38caac in ACE_TP_Reactor::handle_events (this=0x6be18, max_wait_time=0x0) at TP_Reactor.cpp:171 #25 0xfe3892e8 in ACE_Reactor::handle_events (this=0x6be18, max_wait_time=0x0) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/ace/Reactor.inl:166 #26 0xfe60107c in TAO_Leader_Follower::wait_for_event (this=0x6bd98, event=0xffbec928, transport=0x0, max_wait_time=0x0) at Leader_Follower.cpp:390 #27 0xfe5c4d80 in TAO::Synch_Twoway_Invocation::wait_for_reply ( this=0xffbecc20, max_wait_time=0x0, rd=@0x0, bd=@0xffbec910) at Transport.inl:40 #28 0xfe5c4bb0 in TAO::Synch_Twoway_Invocation::remote_twoway ( this=0xffbecc20, max_wait_time=0x0) at Synch_Invocation.cpp:160 #29 0xfe5c2354 in TAO::Invocation_Adapter::invoke_twoway (this=0xffbeced8, op=@0x1, effective_target=@0xffbecd98, r=@0xffbecd00, max_wait_time=@0xffbecd94) at Invocation_Adapter.cpp:262 #30 0xfe5c2264 in TAO::Invocation_Adapter::invoke_remote_i (this=0xffbeced8, stub=0xfe5c22bc, details=@0xffbece10, effective_target=@0xffbecd98, max_wait_time=@0xffbecd94) at Invocation_Adapter.cpp:229 #31 0xfe5c1e5c in TAO::Invocation_Adapter::invoke_i (this=0xffbeced8, stub=0x935d0, details=@0xffbece10) at Invocation_Adapter.cpp:83 #32 0xfe5c1d78 in TAO::Invocation_Adapter::invoke (this=0xffbeced8, ex_data=0x0, ex_count=0) at Invocation_Adapter.cpp:44 #33 0xff036530 in ATest::test (this=0x93e10) at MTestC.cc:142 #34 0x00022bbc in BTest_i::test (this=0x93e10) at MTest_i.cc:49 #35 0x0001f808 in POA_BTest::test_skel (_tao_server_request=@0xffbed4b8, _tao_servant=0x6f640, _tao_servant_upcall=0x1) at MTestS.cc:1446 #36 0xfe8de8dc in TAO_ServantBase::synchronous_upcall_dispatch (this=0x6f648, req=@0xffbed4b8, servant_upcall=0x1f780, derived_this=0x6f640) at Servant_Base.cpp:233 #37 0x0001fcf4 in POA_BTest::_dispatch (this=0x6f640, req=@0xffbeda88, servant_upcall=0x1f780) at MTestS.cc:1690 #38 0xfe89bd28 in TAO_Object_Adapter::dispatch_servant (this=0x0, key=@0xffbed4b8, req=@0xffbed4b8, forward_to={ptr_ = @0xffbed4a8}) at Object_Adapter.i:180 #39 0xfe89c9dc in TAO_Object_Adapter::dispatch (this=0x6d680, key=@0xffbed524, request=@0xffbed4b8, forward_to={ptr_ = @0xffbed4a8}) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/tao/Pseudo_VarOut_T.inl:131 #40 0xfe62989c in TAO_Adapter_Registry::dispatch (this=0x5c314, key=@0xffbed524, request=@0xffbed4b8, forward_to={ptr_ = @0x6f636174}) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/tao/Pseudo_VarOut_T.inl:131 #41 0xfe642fcc in TAO_Request_Dispatcher::dispatch (this=<incomplete type>, orb_core=0x5c188, request=@0xffbed4b8, forward_to={ptr_ = @0x6f6a6563}) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/tao/Tagged_Profile.i:23 #42 0xfe66aa08 in TAO_GIOP_Message_Base::process_request (this=0x95640, transport=0x83f08, cdr=@0xffbed638, output=@0xffbed670, parser=0x95668) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/tao/Object.i:64 #43 0xfe66a4f8 in TAO_GIOP_Message_Base::process_request_message ( this=0x95640, transport=0x83f08, qd=0x0) at GIOP_Message_Base.cpp:700 #44 0xfe64ae1c in TAO_Transport::process_parsed_messages (this=0xfe66a2fc, qd=0xffbed9d8, rh=@0x95640) at Transport.cpp:1810 #45 0xfe649e6c in TAO_Transport::handle_input (this=0x83f08, rh=@0xffbedec0, max_wait_time=0x0) at Transport.cpp:1282 #46 0xfe650bc0 in TAO_Connection_Handler::handle_input_eh (this=0x83de4, h=13, eh=0x83d48) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/tao/Connection_Handler.inl:19 #47 0xfe661fd0 in TAO_IIOP_Connection_Handler::handle_input (this=0x83d48, h=13) at IIOP_Connection_Handler.cpp:168 #48 0xfe38d694 in ACE_TP_Reactor::dispatch_socket_event (this=0x6be18, dispatch_info=@0x1) at TP_Reactor.cpp:657 #49 0xfe38cfb0 in ACE_TP_Reactor::handle_socket_events (this=0x6be18, event_count=@0xffbee0b4, guard=@0x1) at TP_Reactor.cpp:499 #50 0xfe38cc64 in ACE_TP_Reactor::dispatch_i (this=0x6be18, max_wait_time=0xffbee0b4, guard=@0xffbee128) at TP_Reactor.cpp:266 #51 0xfe38caac in ACE_TP_Reactor::handle_events (this=0x6be18, max_wait_time=0xffbee2a0) at TP_Reactor.cpp:171 #52 0xfe3892e8 in ACE_Reactor::handle_events (this=0x6be18, max_wait_time=0xffbee2a0) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/ace/Reactor.inl:166 #53 0xfe5f8eb4 in TAO_ORB_Core::run (this=0x5c188, tv=0xffbee2a0, perform_work=0) at ORB_Core.cpp:1893 #54 0x00028134 in main (argc=2, argv=0xffbee2a0) at /tools/chameleon_tao_common/tao1.4.2/ACE_wrappers/TAO/tao/Pseudo_VarOut_T.inl:58
The compiler that was used was gcc 3.3, not HP as in original bu submission.
Accepting the bug
How to run the test harness... Assuming that you have compiled the sources, there are two tests which need to be performed which demonstrate the problem. Both tests result in the server crashing (asserting), but the crash is not the problem, the crash is just a means to get hold of the stack frames, which need to be examined by the tester to detect the problem! Thus an assert() instruction has been placed at a particular point in the servant code to facilitate this. Without the assert both tests would succeed and there is very little to go by. Both tests involve a common operation performed by a client. The upcall from the client in turn makes a call on a collocated object in the server, and this is the area of study. TEST 1: ======= Purpose: Testing server, client with IMR involved. i. First install the IMR by starting up the ImplRepoService and ImR_Activator deamons. Choose a particular port for the ImplRepoService. Register the server with the IMR using tao_imr tool. Your IMR registry should then list the following: ghost::direct_collocation> ghost::direct_collocation> tao_imr -ORBInitRef ImplRepoService=corbaloc:iiop:1.2\@ghost:2000/ImplRepoService list -v Server <SRV> Activator: ghost Command Line: /home/projects/chameleon/src/direct_collocation/server -- -ORBUseIMR 1 -ORBInitRef ImplRepoService=corbaloc:iiop:1.2@ghost:2000/ImplRepoService -ORBCollocation global -ORBCollocationStrategy direct Working Directory: Activation Mode: NORMAL Running at endpoint: corbaloc:iiop:1.2@ghost:54218/ ghost::direct_collocation> ii. Now run up the server as follows: ghost::direct_collocation> /home/projects/chameleon/src/direct_collocation/server -- -ORBUseIMR 1 -ORBInitRef ImplRepoService=corbaloc:iiop:1.2@ghost:2000/ImplRepoService -ORBCollocation global -ORBCollocationStrategy direct & wait for requests [3] 4543 ghost::direct_collocation> iii. You can see the server is waiting for requests... Now run the client. The client automatically makes a request to the server. You don't need to do anything. Server will then assert (notice that it is the job that was started above). ghost::direct_collocation> ghost::direct_collocation> ./client -ORBInitRef ImplRepoService=corbaloc:iiop:1.2@ghost:2000/ImplRepoService ior =IOR:000000000000000100000000000000010000000000000040000102000000000667686f73740007d00000002514010f004e55500000000d000000000000000100535256000000000000000001425465737400000800000000 Assertion failed: 0, file MTest_i.cc, line 66 COMM_FAILURE (IDL:omg.org/CORBA/COMM_FAILURE:1.0) [3] + Abort(coredump) /home/projects/chameleon/src/direct_collocation/server -- -ORBUseIMR 1 -ORBInitRef ImplRepoService=corbaloc:iiop:1.2@ghost:2000/ImplRepoService -ORBCollocation global -ORBCollocationStrategy direct & ghost::direct_collocation> ghost::direct_collocation> ghost::direct_collocation> iv. Take a look at the stack frames. You should be able to identify a very large stack frame which exhibits the call going remote on a collocated object. Refer to stack frames that I orignally submitted with the PR. TEST 2: ======= Purpose: testing server, client (without IMR involved). i. Simply start up the server. ghost::direct_collocation> ghost::direct_collocation> ghost::direct_collocation> /home/projects/chameleon/src/direct_collocation/server -- -ORBCollocation global -ORBCollocationStrategy direct & wait for requests [3] 4543 ghost::direct_collocation> ii. Now run the client. Again the server will assert. ghost::direct_collocation> ghost::direct_collocation> ./client ior =IOR:000000000000000100000000000000010000000000000040000102000000000667686f73740007d00000002514010f004e55500000000d000000000000000100535256000000000000000001425465737400000800000000 Assertion failed: 0, file MTest_i.cc, line 66 COMM_FAILURE (IDL:omg.org/CORBA/COMM_FAILURE:1.0) [3] + Abort(coredump) /home/projects/chameleon/src/direct_collocation/server -- -ORBCollocation global -ORBCollocationStrategy direct & ghost::direct_collocation> ghost::direct_collocation> ghost::direct_collocation> iii. Take a look at the stack frames. You should be able to identify a medium sized stack frame in which the call does not go remote and shows that collocation optimisation is working correctly. ADDITIONAL NOTE: Our own investigation has established that when the IMR is involved, the object is created with the is_collocated flag false. When the call is made on the collocated object, because it is false it uses a remote-proxy-broker. When the location-forward exception is received it continues to use the remote-proxy-broker which appears to be the problem. It appears that there needs to be a way to replace the proxy broker on the fly with the collocated-proxy-broker so that the call can be sent straight to the servant. Thus the solution is not simply a matter of changing the value of the is_collocated flag to true when we receive the location-forward exception. We also need to change the proxy-broker...
Added dependency
Tidied up CC list of bug report.
Created attachment 288 [details] Output of GNU diff containing the changes
INTRODUCTION It is a known TAO bug (bugzilla 133 and 1919) that the ORB does not take advantage of the collocation optimization for a persistent object when the IMR is being used. The root of the problem is that the ORB is unable to distinguish if the proxy object is collocated because it carries the hostname and port of IMR as endpoint information, which leads the ORB to conclude the servant is remote (i.e. that the proxy object is not collocated). The consequence of this is that a request made on the object will go remote, it will get looped back on the socket, and passes again through the ORB reactor. This leads to two reactor threads and numerous other bugs start to manifest. POSSIBLE SOLUTIONS 1. One possible solution is to tolerate the remote invocation strategy initially, and when a LOCATION_FORWARD ReplyStatus is received, the code can check if the forward profiles are in fact collocated with the servant. (This could be done in Invocation_Adapter::object_forwarded() method located in $TAO_ROOT/tao/Invocation_Adapter.cpp file.) In the case where the forward profiles match the local endpoint the is_collocated flag can be modified to true and the cpb pointer initialised. Unfortunately this strategy has a major disadvantage. Each new proxy, object for a persistent object, will be initially marked as non-collocated and communication with the IMR is required to rectify it. Considering that proxy objects are usually short-lived entities, used for only one or two request invocations, the overhead of repeatedly communicating with the IMR is inefficient and unacceptable. 2. A better approach is to determine collocation during constuction of the proxy object (instead of leaving it to when a request is sent). And how can this be done? In order to create a proxy object (CORBA::Object) the corresponing stub object is required. The stub object contains the endpoints and the ObjectKey of the servant. The ObjectKey contains the POA system id and object_id. In the case where the proxy is a persistent object, the endpoint is the endpoint of IMR. In fact if the stub (or profile if you like), of a proxy object containts the endpoint of IMR it simply means one of two things. Either the proxy corresponds to a corba object created from the POA that resides at the IMR, or from a POA that is registered with the IMR by some CORBA server. Assuming that it is not possible to create a persistent POA with the same name as that of the POA of the IMR ("ImplRepoService"), it is easy to determine if the POA referenced by the ObjectKey exists in the same server. To this end the TAO_Object_Adapter::find_poa() method can be used. If a POA with the same system name is found, and if it is a persistent POA that uses the IMR, collocation between proxy object and servant can be inferred. Is this logic reasonable? IMPLEMENTATION DESCRIPTION We went ahead and implemented the second solution, however in the process we came across some additional bugs. These additional bugs are described towards the end of this mail. In some cases we have fixed these secondary bugs in others we have simply found work-arounds. As stated determination of collocation is needed when the proxy object is created. Recall that a proxy object can be created in various ways. Either by calling the static method CORBA::ORB::string_to_object(); or by calling one of the methods of TAO_POA class that return a CORBA::Object* (like id_to_reference(), servant_to_reference(), e.t.c.); or by using the _this() method. The _this() method is the trivial case. It works just fine as is and it creates a collocated proxy object. So no changes were needed there. The other three methods however needed attention/changes. Firstly lets consider how they PREVIOUSLY worked: The method CORBA::ORB::string_to_object() uses the IOR string to create a stub object, it then tries to determine if the proxy object is collocated. It constructs the appropriate TAO_MProfile and calls TAO_ORB_Core::create_object() method (file ORB_Core.cpp), which checks if it should create a collocated or a non-collocated object. The checking is performed in TAO_ORB_Code::is_collocated() method. The decision is based on the comparison between the endpoints containted in TAO_MProfile and the endpoints of the ORB. If these endpoints are equivalent a collocated proxy object is created. When the IMR is used, the check for collocation fails to detect collocation, and a non-collocated object is always created. If the IMR is not used the method can sucessfully detect collocation and, in the case where the object is deemed collocated, it proceeds to locate the corresponding servant. The POA proxy object creation methods id_to_reference() and servant_to_reference() both lock the POA by grabbing the mutex (ensuring exclusive use of POA). They then call the TAO_POA::key_to_object() method. This method checks if the POA is persistent and if the IMR is being used. If the answer to one of these questions is negative, things are simple. It calls TAO_POA::key_to_stub_i() to create the stub object and uses the new CORBA::Object instance. If on the other hand the POA is persistent and the IMR is being used, things are more complicated. In this case a corbaloc IOR for the object is created (using the endpoint of the IMR) and after that string_to_object() is called. From the corbaloc the appropriate profiles and the stub object are created. After that the code checks the profiles to determine if the proxy is collocated. As mentioned in the previous paragraph the string_to_object() method fails to detect correctly that the object is collocated (when the IMR is used). Now lets consider HOW TO FIX the problem: At first glance it would seem that if we fixed the logic in the string_to_object() all our troubles would go away, since both id_to_reference() and servant_to_reference() rely on string_to_object(). However there is a problem here. Recall that the id_to_reference() and servant_to_reference() methods lock the POA. If the string_to_object() method is fixed, it will go on to locate the servant and since this operation attempts to get the POA mutex deadlock will result. Hence we see that there is a design problem with id_to_reference() and servant_to_reference() calling string_to_object(). To get around this problem a slight redesign was needed. We eliminated the need for id_to_reference() and servant_to_reference() to call string_to_object(). The detail of the changes are as follows: 1.) The method TAO_ORB_Core::is_collocated() was enhanced to perform additional checks in the case where the endpoints of the IOR did not match the ORB endpoints (and the IMR is used). Specifically if the comparison fails between the endpoints of TAO_MProfile and ORB, an additional check is performed. The endpoints of TAO_MProfile are examined and compared with the endpoint of IMR. If this is true it goes on to consider the POA system_id from the IOR string. It then proceeds to search the POA hierarchy usingTAO_Object_Adapter::find_poa() for a persistent POA with the same name. If it finds such a POA and that POA is persistent, it can deem the object as collocated. The code that performs the additional comparisons between the endpoints was added in $TAO_ROOT/tao/ORB_Core.cpp file. For checking if the POA system_id contained in the IOR exists in the same process with the orb. A new pure virtual method in TAO_Adapter class was added (file $TAO_ROOT/tao/Adapter.h). This method is implemented in TAO_Object_Adapter and TAO_Table_Adapter classes that inherit from TAO_Adapter class. The return type of this method is int (as it is the return type of TAO_ORB_Core::is_collocated() method from which the new method is called). It returns 1 if the check succeeds. The implementation of that method for TAO_Table_Adapter always returns 0 (non-collocated case). The affected files are $TAO_ROOT/tao/PortableServer/Object_Adapter.h and $TAO_ROOT/tao/PortableServer/Object_Adapter.cpp (for TAO_Object_Adapter) and $TAO_ROOT/tao/IORTable/Table_Adapter.h and $TAO_ROOT/tao/IORTable/Table_Adapter.cpp (for TAO_Table_Adapter). With this new method TAO_ORB_Core class is able to correctly determine if it should create a collocated object or not. 2.) In the case of id_to_reference() and servant_to_reference(), as mentioned they no longer call string_to_object(). They now work as follows: Firstly the TAO_POA::key_to_object() no longer distinguishes between the two cases (transient or persistent). It simply asks from TAO_POA::key_to_stub_i() to create the stub object which it uses to create the collocated object. Instead the method key_to_stub_i() is responsible for creating the proper stub object depending on whether the IMR is used. In a nutshell, the method checks whether the IMR should be used. In that case it creates a corbaloc IOR with the appropriate format and it gives it to the connector registry to create the corresponding TAO_MProfile. This is used to create the corresponding TAO_Stub object. In the case where the IMR is not used, the code of key_to_stub_i() remains unchanged. 3.) Another problem was that the client interceptors were called even when the direct collocation is used. The method TAO_Collocated_Invocation::invoke() implemented in $TAO_ROOT/tao/Collocated_Invocation.cpp did not take into consideration the Collocation_Strategy flag and Client Interceptors were called in both cases. This was rectified by taking into account the Collocation_Strategy flag. OTHER BUGS ENCOUNTERED ALONG THE WAY (BUT NOT ADDRESSED) 1. Deadlock in wait_for_non_servant_up_call_to_complete() refer to bugzilla 1926. Although this bug is a side-effect of the collocation direct not working, which leads to a second reactor thread getting involved when the servant's destructor makes a call on an object. The collocation defect is not solely to blame. In particular the same situation could conceivably arise when "-ORBCollocation no" is specified and without the IMR. Here proxy objects are always treated as remote and deadlock will result between the non-servant upcall thread and the servant upcall thread. 2. Incoming requests that are queued at the reactor have been observed to get dispatched before orb.run() has been called! Typically a programmer inserts his vital initialisation code before the orb.run() call. What we have seen is that the call is dispatched before the initialisation code has completed, and orb.run() is called. How is this happening? With the collocation defect, if the initialisation code happens to make a call on a collocated object the call will end up going remote and pass through the reactor! It will do a wait, and instead of finding the response, it will find the queued incoming request which it promptly carries out. Thus in effect although the reactor has not been started, as soon the main thread heads towards the reactor, it is highjacked by the reactor for regular usage. This would appear to be a serious problem which cannot simply be blamed on collocation not working. Note that we cannot simply park the POA manager in the halt state until orb.run() is called, because that will mean that our calls on collocated object that go via the reactor have no chance of getting handled! Maybe the MT_NOUPCALL in the upcoming TAO 1.4.3 is a satisfactory remedy... 3. If direct collocation is used, and the servant is deleted, collocated proxy objects may still be around after the servant is deleted. If a call is subsequently made on a collocated proxy object it will result in a crash because the servant pointer is no longer valid. There should be some additional mechanisms to prevent this from happening and ideally the same behaviour should be obtained as that experienced when the proxy object is located in another process, i.e. an exception is thrown that the servant no longer exists. 4. If thru_poa collocation strategy is used, server request interceptors are not called. According to "Collocation Optimizations for CORBA" pdf document, located in http://www.cs.wustl.edu/~schmidt/PDF/C++-report-col18.pdf, interceptors should be called in the case of the thru_poa collocation strategy. This is not happening. That deficient code is located in the skeleton file which is generated by the TAO_IDL compiler. Supposing that an idl file named A exists and that file defines a B interface, idl compiler generates a AS.cpp file which contains the definition of _TAO_B_Strategized_Proxy_Broker::dispatch() method. This method checks which strategy is used, so this is the appropriate point for addressing that problem. SIDE EFFECTS OF THE SOLUTION (IMPORTANT) The above solution has a big side-effect. The searching of POAs requires locking of the TAO_Object_Adapter. The above means that methods TAO_ORB_Core::create_object() and all other methods which use that (as CORBA::ORB::string_to_object), have been made as Non_Servant_Upcalls. Thus if a method holding the lock of TAO_Object_Adapter is going to call TAO_ORB_Core::create_object() or CORBA::ORB::string_to_object() it must create a Non_Servant_Upcall object. This is a big change which has not been attempted. Instead we have employed the following work-around: A new method, named 'persistent_poa_exists()' has been defined on TAO_Object_Adapter::Hint_Strategy and on the derived classes. This method searches the persistent_poa_system_map to find the POA. For the duration of that search no locking is attemped (!!!!!), or else a deadlock may occur. This is bad and it must change. When this is oneday addressed, and all methods calling TAO_ORB_Core::create_object() will release the lock before the call, the TAO_Object_Adapter::find_poa() method can be used instead. In that case a lock acquire must be added in TAO_Object_Adapter::is_collocated(). Method TAO_Object_Adapter::find_poa() makes use of TAO_Object_Adapter::Hint_Strategy::find_persistent_poa(), which calls TAO_Object_Adapter::activate_poa() if poa is not found in persistent_poa_system_map. This methods creates a Non_Servant_Upcall() object, therefore it is supposed that lock is already acquired. This is not always true in our case, thus the call to activate_poa() should be avoided. New method persistent_poa_exists searches only the persistent_poa_system_map (the activate_poa() call is really needed?), without trying to acquire the lock because it may be called from a function with the lock already acquired.Thus, if we want to protect that code and make it thread-safe, the lock must be released before starting the collocation check. Bellow, the version numbers of the files used as source are given. The output of GNU diff utility containing the changes has been attached to this message. $ACE_ROOT/TAO/tao/Adapter.h v 1.23 $ACE_ROOT/TAO/tao/Collocated_Invocation.cpp v 1.3 $ACE_ROOT/TAO/tao/IORTable/Table_Adapter.cpp v 1.12 $ACE_ROOT/TAO/tao/IORTable/Table_Adapter.h v 1.9 $ACE_ROOT/TAO/tao/ORB_Core.cpp v 1.511 $ACE_ROOT/TAO/tao/PortableServer/Object_Adapter.cpp v 1.66 $ACE_ROOT/TAO/tao/PortableServer/Object_Adapter.h v 1.38 $ACE_ROOT/TAO/tao/PortableServer/POA.cpp v 1.110
A quick note on Item 4 above regarding missing server side interception points when using thru_POA collocation: TAO_IDL generated skeletons are currently undergoing an overhaul, as described in bug 1369. That effort will address the missing thru_POA intereption points.
A lot of things are already changed in the cvs repository. Could you retest this when x.4.5 has been released in some weeks?
Hi Johny First of all a quick clarification: the title of this PR should read "Collocation optimization does not work when ImR is used". As it failed both with thru_poa and direct, in the past. Not just 'direct'. I built TAO1.4.5 on a linux PC, in order to try out the collocation support in the new release, as you requested. I also build the test harness that I submitted with this Bugzilla report (1919), and I followed the exact same steps that I described in an earlier submission. Except that I test with CollocationOptimisation thru_poa instead of direct to avoid other complications. Unfortunately the test still fails when Collocation is being used in conjunction with the Implementation Repository. That is to say, we still see that Collocation optimisation works fine so long as the server does not "use the ImR" option, and conversely the same test run with -ORBUseIMR 1 and -ORBInitRef <IMR corbaloc> fails. In the past we saw that when the ImR was used as well, it failed to detect collocation and calls on collocated objects went remote. Now however, we see that it is detecting that the object is collocated (which is an improvement), but the cpb_ point is apparently not setup and collocated optimisation fails. (This does not happen if we omit -ORBUseIMR 1. In this case the cpb_ pointer is correctly setup and collocation optimization works.) We are getting the following assert: ACE_ASSERT: file Invocation_Adapter.cpp, line 163 assertion failed for 'cpb_ != 0'.Aborting... Aborted (core dumped) The associated stack at time of crash is as follows: #0 0xffffe410 in ?? () #1 0xbfffb308 in ?? () #2 0x00000006 in ?? () #3 0x000018b6 in ?? () #4 0x40707d41 in raise () from /lib/tls/libc.so.6 #5 0x40709529 in abort () from /lib/tls/libc.so.6 #6 0x404a91fe in ACE_Log_Msg::log (this=0x0, format_str=0x403387ae "", log_priority=LM_ERROR, argp=0xbfffc5d4 "\001") at OS_NS_stdlib.inl:46 #7 0x404a9e26 in ACE_Log_Msg::log (this=0x805b450, log_priority=LM_ERROR, format_str=0x40338774 "ACE_ASSERT: file %N, line %l assertion failed for '%s'.%a\n") at Log_Msg.cpp:914 #8 0x4028fef4 in TAO::Invocation_Adapter::invoke_collocated_i (this=0xbfffc7b0, stub=0x808ef00, details=@0xbfffc710, effective_target=@0xbfffc6b0, strat=TAO_CS_THRU_POA_STRATEGY) at Invocation_Adapter.cpp:192 #9 0x40290187 in TAO::Invocation_Adapter::invoke_i (this=0xbfffc7b0, stub=0x808ef00, details=@0xbfffc710) at Invocation_Adapter.cpp:101 #10 0x40290359 in TAO::Invocation_Adapter::invoke (this=0xbfffc7b0, ex_data=0x0, ex_count=0) at Invocation_Adapter.cpp:44 #11 0x402e804c in TAO::Remote_Object_Proxy_Broker::_is_a (this=0x403c1300, target=Internal: global symbol `Object' found inObject.cpp psymtab but not in symtab. Object may be an inlined function, or may be a template function (if a template, try specifying an instantiation: Object<type>). ) at Remote_Object_Proxy_Broker.cpp:38 #12 0x402af3af in CORBA::Object::_is_a (this=0x808eaa8, type_id=0x40554538 "IDL:ATest:1.0") at Object.cpp:216 #13 0x405535e9 in TAO::Narrow_Utils<ATest>::narrow (obj=Variable "obj" is not available. ) at Object_T.cpp:27 #14 0x4055238b in ATest::_narrow (_tao_objref=0x808eaa8) at MTestC.cc:178 #15 0x08053e86 in BTest_i (this=0x808eb98) at Pseudo_VarOut_T.inl:66 #16 0x08054e52 in main (argc=2, argv=0xbfffcbc4) at Srv_Main.cc:46 I should stress that this crash takes place when we start up the server! We don't even get as far as running the client. (However, without -ORBUseIMR 1 the server does not crash, and we are able to conduct the test successfully). Please let me know if you need any addition info. I will at some point try to see if I can apply George's original (gtsal@intracom.gr) patches to the new TAO1.4.5, but I fear that after the refactoring this is going to be non-trivial task. I will let you know if I manage to do this. Regards, Kostas Lykiardopoulos.
... a further comment to the above submission, I said that there was a small improvement in that it now appears to detect collocation, however this is not too surprising because the particular bit of code just creates a CORBA object proxy using POA->id_to_reference() and in this case setting is_collocated is trivial. I suspect this also worked in the past. The real test is when the call is made using the IOR string, after a "string to object". Unfortunately, as I explained, I don't get to this point due to the new crash. Thus the ultimate proof is to test with the client as well. Here we may still find that it does not detect collocation... as in the past.
There is a new option in the latest TAO that will let you get a direct object reference for use within a server that has object registered with the ImR. If you start a server with -ORBUseImR 1, then as you know, all object references created from persistent POAs will have the address of the ImR. This created a problem when using the IORTable, because you want the registered IORs to have the address of the server itself to avoid an extra round-trip through the ImR. For this reason, I added a new bool argument to id_to_reference_i(), which allows you to explicitly request a direct object reference instead of the default indirect reference even though -ORBUseImR 1 is specified. TAO_Root_POA* poa = dynamic_cast<TAO_Root_POA*>(root_poa.in()); obj = tmp_poa->id_to_reference_i (id.in (), false); String_var ior = orb->object_to_string(obj.in()); In this case obj is direct object reference, and you can use catior to verify that the ip address of the server itself is encoded. This direct object reference can be used in lieu of the normal indirect version, and any collocation optimizations should work as usual. You can also pass this IOR to other (possibly collocated) clients, and they will bypass the ImR completely. Of course, the whole point of the ImR is to add an extra level of indirection, but it might definitely make sense to use the direct object reference for all collocated clients. Justin Michel OCI
Yesterday the assert has been changed in the following by Ossama, could you retest this? ACE_ASSERT (cpb_ != 0 || (strat == TAO_CS_THRU_POA_STRATEGY && effective_target->_servant () != 0));
Created attachment 334 [details] Patch for TAO1.4.5
I submit the patch required to get collocation optimisation to work in TAO1.4.5. It appears to be a lot simpler than in TAO1.4.3. Only change needed is in Root_POA.cpp and mainly in the method key_to_object(). Please see the above attached diff file that was generated with "diff -u": "05/25/05 10:52 Patch for TAO1.4.5 (text/plain)". I have tested the patched code, together with the patch to the Invocation_Adapter.cc by Ossama, with the test harness that I submitted earlier in this thread some months ago. Johnny/Justin could you please see if you can add this patch to the working version (live version) of TAO. Thanks, Kostas Lykiardopoulos.
The collocation optimisation patch that I provided on 05/25/05 10:52 is incomplete. It works in the case where the servant for the object in question is incarnated. However, it does not address the situation where the collocated object has not yet been activated. I am still working on a solution for this. It appears that the updated profile information that is received in the location_forward response from the ImR is not being taken into account to update the collocation status of the object. Hence the Invocation_Adapter still "sees" the object as remote despite the fact that ImR has notified it otherwise, which results in invoke_i() calling invoke_remote_i...
several bugs in this area are fixed, please retest with the x.5 that is available Feb 28th, or try the cvs version
reassign to reporter, can you retest this with the x.5 release of TAO, a lot has been fixed in this area.
A charitable deed for the day... I have retested this with TAO 1.5.1 and am please to report that the problem that we experienced is now fixed. Calls made on collocated objects no longer go via the IMR, except for the initial is_a(). I have tested with 'thru_poa' collocation optimisation instead of 'direct' though.