Bug 1919 - Collocation direct optimization does not work when ImR is used
Summary: Collocation direct optimization does not work when ImR is used
Status: RESOLVED FIXED
Alias: None
Product: TAO
Classification: Unclassified
Component: ORB (show other bugs)
Version: 1.5
Hardware: SPARC Solaris
: P3 major
Assignee: klyk
URL:
Depends on: 133 2289
Blocks: 2454
  Show dependency tree
 
Reported: 2004-09-06 00:51 CDT by klyk
Modified: 2006-05-25 00:40 CDT (History)
1 user (show)

See Also:


Attachments
Output of GNU diff containing the changes (20.02 KB, patch)
2004-10-15 05:06 CDT, gtsal
Details
Patch for TAO1.4.5 (3.46 KB, patch)
2005-05-25 10:52 CDT, klyk
Details

Note You need to log in before you can comment on or make changes to this bug.
Description klyk 2004-09-06 00:51:10 CDT
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
Comment 1 klyk 2004-09-06 00:54:41 CDT
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

Comment 2 klyk 2004-09-16 01:02:09 CDT
The compiler that was used was gcc 3.3, not HP as in original bu submission.
Comment 3 Nanbor Wang 2004-09-20 14:33:06 CDT
Accepting the bug
Comment 4 klyk 2004-09-21 04:34:37 CDT
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...
Comment 5 Johnny Willemsen 2004-09-21 05:23:45 CDT
Added dependency
Comment 6 klyk 2004-09-22 00:45:52 CDT
Tidied up CC list of bug report.
Comment 7 gtsal 2004-10-15 05:06:37 CDT
Created attachment 288 [details]
Output of GNU diff containing the changes
Comment 8 gtsal 2004-10-15 05:09:43 CDT
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

Comment 9 Ossama Othman 2004-10-15 13:49:45 CDT
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.
Comment 10 Johnny Willemsen 2005-03-25 04:07:22 CST
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?
Comment 11 klyk 2005-05-20 06:54:27 CDT
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.
Comment 12 klyk 2005-05-20 07:05:38 CDT
... 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. 
Comment 13 Justin Michel 2005-05-23 15:18:53 CDT
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
Comment 14 Johnny Willemsen 2005-05-25 08:05:59 CDT
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)); 
Comment 15 klyk 2005-05-25 10:52:43 CDT
Created attachment 334 [details]
Patch for TAO1.4.5
Comment 16 klyk 2005-05-25 10:54:32 CDT
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.


Comment 17 klyk 2005-05-30 10:03:19 CDT
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...
Comment 18 Johnny Willemsen 2006-02-23 10:03:45 CST
several bugs in this area are fixed, please retest with the x.5 that is
available Feb 28th, or try the cvs version
Comment 19 Johnny Willemsen 2006-03-21 05:18:35 CST
reassign to reporter, can you retest this with the x.5 release of TAO, a lot has
been fixed in this area.
Comment 20 klyk 2006-05-25 00:40:27 CDT
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.