[omniORB] omniORB 4.3: exceptionIdInAny config parameter

pascal.moucheront at univ-eiffel.fr pascal.moucheront at univ-eiffel.fr
Wed May 18 16:36:48 UTC 2022


> [...]
> Can you come up with a minimal test that shows the problem and post it?
> 
> Duncan.

Sure,

I stripped down one of the tests from our test suite,
and used your 'echo' and 'anyExample' as a starting point to reproduce the problem.

The remote object has one function, taking an Any as input argument, and returning an Any.
A special value of the argument triggers an user exception in the remote object.
We need to catch this exception in the client.

In the two first cases,
when we call the function synchronously, everything is OK.

In the third case,
when we call the function with an asynchronous call, and do not trigger the user exception,
eveything is OK regardless of exceptionIdInAny value.

In the fourth case,
when we call the function with an asynchronous call, and we trigger the user exception,
the result depends on the value of exceptionIdInAny config parameter.

If exceptionIdInAny = 1, we get:
   Caught a CORBA::MARSHAL
   unexpected CORBA::SystemException,  name = MARSHAL repo = IDL:omg.org/CORBA/MARSHAL:1.0

If exceptionIdInAny = 0, everything is ok:
   repy arrived
   Caught expected exception: MyExcept, MyExcept IDL:MyExcept:1.0 "Server throws at call n°4"

The code for the three files echoExcept.idl, eg2e_impl.cc and eg2eclt.cc is below
(I don't know if attached files are allowed on the mailing list)
I compiled them with src/examples/echo directory, linking with omniORB4 and omniDynamic4

Best Regards
Pascal Moucheront


--- echoExcept.idl ------------------------------------------------------
#ifndef __ECHOEXCEPT_IDL__
#define __ECHOEXCEPT_IDL__

exception MyExcept
{
    string reason;
};

interface EchoE {
  any echoExcept(in any argin) raises(MyExcept);
};

#endif  // __ECHOEXCEPT_IDL__

--- eg2e_impl.cc --------------------------------------------------------
// eg2e_impl.cc - Modified example 2 to test for exception in Any propagation
//
//               This is the object implementation.
//
// Usage: eg2e_impl
//
//        On startup, the object reference is printed to cout as a
//        stringified IOR. This string should be used as the argument to
//        eg2_clt.
//

#include <echoExcept.hh>

#include <iostream>
#include <sstream>
#include <cstring>
using namespace std;

class EchoE_i : public POA_EchoE
{
  int nCall;
  CORBA::Any argout;

public:
  inline EchoE_i() : nCall(0) {}
  virtual ~EchoE_i() {}
  virtual char* echoString(const char* mesg);
  virtual CORBA::Any* echoExcept(const CORBA::Any& argin);
};


char* EchoE_i::echoString(const char* mesg)
{
  cout << "Upcall: " << mesg << endl;
  return CORBA::string_dup(mesg);
}

CORBA::Any* EchoE_i::echoExcept(const CORBA::Any& argin)
{
  ostringstream oss;
  const char* mesg;
//  const char* reply;

  nCall++;

  // extraire une chaîne de l'Any argin
  if (argin >>= mesg)
  {
    // The storage of the extracted string is still owned by the any.
    cout << "Upcall: " << mesg << endl;

    int th = strncmp(mesg,"NO",2);
    if( th == 0 )
    {
      oss << "Server called " << nCall << " times.";
      cout << oss.str() << endl;
    }
    else
    {
      oss << "Server throws at call n°" << nCall;
      cout << oss.str() << endl;
      throw MyExcept(oss.str().c_str());
    }
  }
  else
  {
    oss << "Bad argument";
    cout << "Upcall: " << oss.str() << endl;
    throw MyExcept(oss.str().c_str());
  }

  CORBA::Any* argout = new CORBA::Any;
  *argout <<= oss.str().c_str();
  cout << "Returning Any containing: string: " << oss.str() << endl;
  return argout;
}

//////////////////////////////////////////////////////////////////////

int main(int argc, char** argv)
{
  try {
    CORBA::ORB_var          orb = CORBA::ORB_init(argc, argv);
    CORBA::Object_var       obj = orb->resolve_initial_references("RootPOA");
    PortableServer::POA_var poa = PortableServer::POA::_narrow(obj);

    PortableServer::Servant_var<EchoE_i> myecho = new EchoE_i();
      
    PortableServer::ObjectId_var myechoid = poa->activate_object(myecho);

    // Obtain a reference to the object, and print it out as a
    // stringified IOR.
    obj = myecho->_this();
    CORBA::String_var sior(orb->object_to_string(obj));
    cout << sior << endl;

    PortableServer::POAManager_var pman = poa->the_POAManager();
    pman->activate();

    // Block until the ORB is shut down.
    orb->run();
  }
  catch (CORBA::SystemException& ex) {
    cerr << "Caught CORBA::" << ex._name() << endl;
  }
  catch (CORBA::Exception& ex) {
    cerr << "Caught CORBA::Exception: " << ex._name() << endl;
  }
  return 0;
}

--- eg2e_clt.cc ---------------------------------------------------------
// eg2e_clt.cc - Modified example 2 to test for exception propagation.
//
//              This is the client. The object reference is given as a
//              stringified IOR on the command line.
//
// Usage: eg2e_clt <object reference>
//

#include <echoExcept.hh>

#include <iostream>
#include <unistd.h>
using namespace std;


void doSyncCall(EchoE_ptr& obj, const char* msg)
{
  CORBA::Any a;
  a <<= msg;

  CORBA::Any_var bp;
  bp = obj->echoExcept(a);

  cout << "   Operation completed. Returned an Any containing ";
  const char* reply;
  if (bp >>= reply) {
    cout << "the string: \"" << reply << "\"" << endl;
  }
  else {
    cout << "an unknown value with TypeCode.kind() = "
         << bp->type()->kind() << endl;
  }
}


CORBA::Request_ptr sendAsyncRequest(EchoE_ptr& obj, const char* msg)
{
  CORBA::Any a;
  a <<= msg;

  // get a request object
  CORBA::Request_ptr request = obj->_request("echoExcept");

  // setup request arguments
  request->add_in_arg() <<= a;
    
  // setup request return type
  request->set_return_type(CORBA::_tc_any);

  // setup request exceptions
  request->exceptions()->add(_tc_MyExcept);

  // execute asynchronous request
  request->send_deferred();
  // or request->send_oneway(); CORBA::release(request);

  return request;
}


void getAsyncReply(CORBA::Request_ptr& req)
{
  if( req->poll_response() )
  {
    cout << "   repy arrived" << endl;
    CORBA::Environment_ptr env;
    env = req->env();

    if( !CORBA::is_nil(env) )
    {
      if( env->exception() == NULL )
      {
        // no exception, the function call return value is embedded in an Any
        CORBA::Any val;
        val = req->return_value();

        // We expect a return value of type Any, containing a string
        CORBA::Any bp;
        if( val >>= bp ) {

          cout << "   Operation completed. Returned an Any containing ";
          const char* reply;
          if (bp >>= reply) {
            cout << "the string: \"" << reply << "\"" << endl;
          }
          else {
            cout << "an unknown value with TypeCode.kind() = "
                 << bp.type()->kind() << endl;
          }
        }
        else {
          cout << "   unexpected function call return value with TypeCode.kind() = "
               << val.type()->kind() << endl;
        }
      }
      else
      {
        // there was an exception
        CORBA::Exception* ex_ptr = env->exception();

        cout << "";

        CORBA::UnknownUserException* unk_ex;
        CORBA::TRANSIENT* tra_ptr;
        CORBA::SystemException* sysex_ptr;
        CORBA::Exception* unkex_ptr;

        // We expect a CORBA::UnknownUserException, containing our MyExcept exception.
        if ((unk_ex = CORBA::UnknownUserException::_downcast(ex_ptr)) != NULL)
        {
          const MyExcept* my_ex;
          if( unk_ex->exception() >>= my_ex )
          {
            MyExcept ex(*my_ex);
            throw ex;
          }
          else
          {
            cout << "   Operation failed. Did not return the expected MyExcept exception!"
                 << endl;
          }
        }
        else
        {
          ex_ptr->_raise();
        }
      }
    }   // end !CORBA::is_nil(env)
    else
    {
       cout << "   repy arrived but request environment NULL" << endl;
    }
  }
  else
  {
    cout << "   repy not yet arrived" << endl;
  }
}


void doAsyncCall(EchoE_ptr& obj, const char* msg)
{
  CORBA::Request_ptr req = sendAsyncRequest(obj,msg);
  sleep(1);
  getAsyncReply(req);
}


void testEchoExcept(EchoE_ptr obj)
{
  cout << "Synchronous call to EchoExcept, should not throw." << endl;
  const char* str1 = "NO Exception";
  try {
    doSyncCall(obj,str1);
  }
  catch (MyExcept& my_ex)
  {
    cerr << "   Caught unexpected exception: MyExcept, "
         << my_ex._name() << " "
         << my_ex._rep_id() << " \""
         << my_ex.reason << "\""
         << endl;
  }

  cout << "\nSynchronous call to EchoExcept, should throw." << endl;
  const char* str2 = "Exception";
  try {
    doSyncCall(obj,str2);
  }
  catch (MyExcept& my_ex)
  {
    cerr << "   Caught expected exception: MyExcept, "
         << my_ex._name() << " "
         << my_ex._rep_id() << " \""
         << my_ex.reason << "\""
         << endl;
  }

  cout << "\nAsynchronous call to EchoExcept, should not throw." << endl;
  try {
    doAsyncCall(obj,str1);
  }
  catch (MyExcept& my_ex)
  {
    cerr << "   Caught unexpected exception: MyExcept, "
         << my_ex._name() << " "
         << my_ex._rep_id() << " \""
         << my_ex.reason << "\""
         << endl;
  }

  cout << "\nAsynchronous call to EchoExcept, should throw." << endl;
  try {
    doAsyncCall(obj,str2);
  }
  catch (MyExcept& my_ex)
  {
    cerr << "   Caught expected exception: MyExcept, "
         << my_ex._name() << " "
         << my_ex._rep_id() << " \""
         << my_ex.reason << "\""
         << endl;
  }
}


//////////////////////////////////////////////////////////////////////

int main(int argc, char** argv)
{
  try {
    CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);

    if (argc != 2) {
      cerr << "usage:  eg2e_clt <object reference>" << endl;
      return 1;
    }

    {
      CORBA::Object_var obj = orb->string_to_object(argv[1]);
      EchoE_var ref = EchoE::_narrow(obj);
      if (CORBA::is_nil(ref)) {
        cerr << "Can't narrow reference to type EchoE (or it was nil)." << endl;
        return 1;
      }
      testEchoExcept(ref);
    }
    orb->destroy();
  }
  catch (CORBA::TRANSIENT& tra) {
    cerr << "Caught system exception TRANSIENT -- unable to contact the "
         << "server." << endl;
//          cout << "   Operation failed. Returned "
//               << "CORBA::TRANSIENT exception,"
//               << " minor = " << tra_ptr->minor() << endl;
  }
  catch (CORBA::SystemException& ex) {
    cerr << "Caught a CORBA::" << ex._name() << endl;
    cerr << "unexpected CORBA::SystemException, "
         << " name = " << ex._name()
         << " repo = " << ex._rep_id() << endl;
  }
  catch (CORBA::Exception& ex) {
    cerr << "Caught CORBA::Exception: " << ex._name() << endl;
    cerr << "unexpected CORBA::Exception "
         << ex._name() << " "
         << ex._rep_id() << endl;
  }
  return 0;
}






More information about the omniORB-list mailing list