[omniORB] Help, this should never happen but...

Duncan Grisby dgrisby@uk.research.att.com
Mon, 02 Apr 2001 12:55:33 +0100


------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <7915.986212446.1@pineapple>

On Friday 30 March, "John D. Heintz" wrote:

[...]
> >   void op(in A the_A);
> > 
> > Now, we're holding an object reference of type B, and pass it to op().
> > Neither the sending or receiving ORB can complain at this stage, since
> > the object might actually have interface C:
> > 
> >   interface C : A, B {};
> 
> Shouldn't the client side be forced to call narrow() to get an A 
> reference?  Or are you saying the server may not want to publish that 
> reference?

The client side doesn't have to call _narrow() since the IDL tells it
the object is of type A. The IDL says A, so the receiving ORB creates
an object reference of type A, even if the ORB's knowledge of the
types suggests that the reference has the wrong type.

It would be bad for the receiving ORB to always contact objects it
receives to check their type. Imagine a service which receives a large
sequence of object references, but only invokes on a few of them. It
would be inefficient for the ORB to contact every single object to
check all the types.

> > All the receiving ORB can do is mark the object reference as having
> > its type unverified. On the first call to the object, its type is
> > checked with a call to _is_a(), and an INV_OBJREF exception is thrown
> > if the type is incorrect.
> 
> Does this mean that the server ORB should check _is_a() and raise an 
> exception?  The behavior we are seeing is that the the call is making it 
> all the way into our python servant with the wrong type of object.  We 
> can call _is_a() or isinstance() ourselves, but that seems wrong.

Yes. You should not see a call reaching the servant object. The only
way that would happen would be if you use the
-ORBverifyObjectExistsAndType 0 command line option, which suppresses
the check.

Here are some example programs which demonstrate the behaviour. Run
srv.py, then run clt.py with the server's IOR as its command line
argument. Run them both with -ORBtraceLevel 10 -ORBtraceInvocations to
see the exceptions being thrown.

The relevant section of the server trace is

omniORB: Creating Python ref to remote: root<16777216>
 target id      : IDL:ObjRefTest/A:1.0
 most derived id: IDL:ObjRefTest/B:1.0
Calling opA()...
omniORB: Invoke '_is_a' on remote: root<16777216>
omniORB: The object with the IR repository ID: IDL:ObjRefTest/B:1.0
 returns FALSE to the query _is_a("IDL:ObjRefTest/A:1.0").
 A CORBA::INV_OBJREF is raised.
omniORB: throw INV_OBJREF from omniObjRef.cc:213

Cheers,

Duncan.


------- =_aaaaaaaaaa0
Content-Type: text/plain; name="test.idl"; charset="us-ascii"
Content-ID: <7915.986212446.2@pineapple>


module ObjRefTest {
  interface A {
    void opA();
  };

  interface B {
    void opB();
  };

  interface Test {
    void doTest(in A the_A);
  };
};

------- =_aaaaaaaaaa0
Content-Type: text/plain; name="srv.py"; charset="us-ascii"
Content-ID: <7915.986212446.3@pineapple>

#!/usr/bin/env python

import sys, traceback, CORBA, PortableServer, ObjRefTest, ObjRefTest__POA

class Test_i (ObjRefTest__POA.Test):

    def doTest(self, the_A):
        print "Calling opA()..."
        try:
            the_A.opA()

        except CORBA.SystemException:

            print "Caught a system exception:"
            traceback.print_exc()
        
        print "Test done"

orb = CORBA.ORB_init(sys.argv, CORBA.ORB_ID)
poa = orb.resolve_initial_references("RootPOA")
ti  = Test_i()
to  = ti._this()

print orb.object_to_string(to)

poaManager = poa._get_the_POAManager()
poaManager.activate()
orb.run()

------- =_aaaaaaaaaa0
Content-Type: text/plain; name="clt.py"; charset="us-ascii"
Content-ID: <7915.986212446.4@pineapple>

#!/usr/bin/env python

import sys, CORBA, PortableServer, ObjRefTest, ObjRefTest__POA

class A_i (ObjRefTest__POA.A):

    def opA(self):
        print "opA() called"

class B_i (ObjRefTest__POA.B):

    def opB(self):
        print "opB() called"

orb = CORBA.ORB_init(sys.argv, CORBA.ORB_ID)
poa = orb.resolve_initial_references("RootPOA")

ai  = A_i()
ao  = ai._this()

bi  = B_i()
bo  = bi._this()

poaManager = poa._get_the_POAManager()
poaManager.activate()

to = orb.string_to_object(sys.argv[1])
to = to._narrow(ObjRefTest.Test)

assert(to is not None)

print "Testing with A reference..."
to.doTest(ao)
print "Test done"

print "Testing with B reference..."
to.doTest(bo)
print "Test done"

------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <7915.986212446.5@pineapple>

-- 
 -- Duncan Grisby  \  Research Engineer  --
  -- AT&T Laboratories Cambridge          --
   -- http://www.uk.research.att.com/~dpg1 --

------- =_aaaaaaaaaa0--