Discussion:
[omniORB] strange behavior of '_this()' method
Michael Kilburn
2009-03-21 06:32:51 UTC
Permalink
Hi,

Recently I've (suddenly :-)) realized that our product never overrides
_defaultPOA() method, but uses non-RootPOA for all objects (for
MAN_THREAD_MODEL) and occasionally calls _this() method. After careful
reading of CORBA standard I came to conclusion that _this() called for
objects that are nor target of currently processed request should return
reference acivated in RootPOA (thus wasting all our efforts to confine
everything to our own POA). But it does not happen, it seems and after some
digging I found why:

void*
PortableServer::ServantBase::_do_this(const char* repoId)
{
?
{
omni_tracedmutex_lock sync(*omni::internalLock);
if (_activations().size() == 1) {
// We only have a single activation -- return a reference to it.
omniObjTableEntry* entry = _activations()[0];
omniOrbPOA* poa = omniOrbPOA::_downcast(entry->adapter());
omniIORHints hints(poa ? poa->policy_list() : 0);
omniObjRef* ref = omni::createLocalObjRef(_mostDerivedRepoId(),
repoId,
entry, hints);
OMNIORB_ASSERT(ref);
return ref->_ptrToObjRef(repoId);
}
}
?
}

Since our servants usually activated only in one POA and usually already
activated before possible _this() call -- this code 'saves' us. But there
are few cases when _this() might be called on non-active object -- and it
behaves as I feared (i.e. gets activated in RootPOA).

Now questions:
- I feel that this (probably helpful) behaviour is not standard-compliant --
can someone prove that it is not the case?
- is there any way to change RootPOA's policies? (to remove ecessity of
creating another POA)
- I am trying to avoid necessity of overriding _defaultPOA (someone will
forget to do it and it will lead to hard-to-find problems). So there any way
to ensure that all objects get activated in specific POA without this?
- maybe it is possible to 'disable' RootPOA somehow?

And one unrelated question:
I have created a ServantManager object and registered it with POA. According
to standard when object is activated _add_ref() is called nspecified number
of times. The question is how many times etherealize() method of
ServantManager should call _remove_ref() when called with
remaining_activations = true? It works with one call -- but is it
guaranteed?


Thanks!
--
Sincerely yours,
Michael.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.omniorb-support.com/pipermail/omniorb-list/attachments/20090320/31740acc/attachment.htm
Michael
2009-03-22 05:09:50 UTC
Permalink
Hi Michael,
Post by Michael Kilburn
Hi,
Recently I've (suddenly :-)) realized that our product never overrides
_defaultPOA() method, but uses non-RootPOA for all objects (for
MAN_THREAD_MODEL) and occasionally calls _this() method. After careful
reading of CORBA standard I came to conclusion that _this() called for
objects that are nor target of currently processed request should return
reference acivated in RootPOA (thus wasting all our efforts to confine
everything to our own POA). But it does not happen, it seems and after some
void*
PortableServer::ServantBase::_do_this(const char* repoId)
{
?
{
omni_tracedmutex_lock sync(*omni::internalLock);
if (_activations().size() == 1) {
// We only have a single activation -- return a reference to it.
omniObjTableEntry* entry = _activations()[0];
omniOrbPOA* poa = omniOrbPOA::_downcast(entry->adapter());
omniIORHints hints(poa ? poa->policy_list() : 0);
omniObjRef* ref = omni::createLocalObjRef(_mostDerivedRepoId(),
repoId,
entry, hints);
OMNIORB_ASSERT(ref);
return ref->_ptrToObjRef(repoId);
}
}
?
}
Since our servants usually activated only in one POA and usually already
activated before possible _this() call -- this code 'saves' us. But there
are few cases when _this() might be called on non-active object -- and it
behaves as I feared (i.e. gets activated in RootPOA).
- I feel that this (probably helpful) behaviour is not standard-compliant --
can someone prove that it is not the case?
Afaik this is in fact standard compliant.
Post by Michael Kilburn
- is there any way to change RootPOA's policies? (to remove ecessity of
creating another POA)
No (this is also defined in the standard)
Post by Michael Kilburn
- I am trying to avoid necessity of overriding _defaultPOA (someone will
forget to do it and it will lead to hard-to-find problems). So there any way
to ensure that all objects get activated in specific POA without this?
You'll have to call activate on the correct poa explicitly (it shouldn't
be hard to verify this, assuming you have a reasonable code structure).
Maybe you should write a get_this helper template that makes sure
everything is activated the way you want it?!?
Post by Michael Kilburn
- maybe it is possible to 'disable' RootPOA somehow?
I don't think so + I don't think it would be any good (poas form a hierachy)
Post by Michael Kilburn
I have created a ServantManager object and registered it with POA. According
to standard when object is activated _add_ref() is called nspecified number
of times. The question is how many times etherealize() method of
ServantManager should call _remove_ref() when called with
remaining_activations = true? It works with one call -- but is it
guaranteed?
Thanks!
------------------------------------------------------------------------
_______________________________________________
omniORB-list mailing list
http://www.omniorb-support.com/mailman/listinfo/omniorb-list
Michael Kilburn
2009-03-22 06:57:41 UTC
Permalink
Hi Michael,
[skipped lengthy description of _this()'s behaviour that tracks
activations and in case if there is only one activation -- it uses POA of
that activation to produce a new reference]
Post by Michael Kilburn
- I feel that this (probably helpful) behaviour is not standard-compliant
--
Post by Michael Kilburn
can someone prove that it is not the case?
Afaik this is in fact standard compliant.
Can't find anything in standard that might allow this, quite opposite --
standard clearly says that if object is not a target of 'Current' request --
_defaultPOA is called to get POA used to lookup a reference or activate (in
case of implicit activation), no optionality.
Can you give me a reference that suports your point of view?
Post by Michael Kilburn
- I am trying to avoid necessity of overriding _defaultPOA (someone will
forget to do it and it will lead to hard-to-find problems). So there any
way
Post by Michael Kilburn
to ensure that all objects get activated in specific POA without this?
You'll have to call activate on the correct poa explicitly (it shouldn't
be hard to verify this, assuming you have a reasonable code structure).
Maybe you should write a get_this helper template that makes sure
everything is activated the way you want it?!?
:-) Our product in constant state of development for last 10? years and will
continue like that for foreseeable future (with developers coming and
leaving). I am pretty much sure that sooner or later one of them will forget
to use a helper or override that function. It is inevitable.
Post by Michael Kilburn
- maybe it is possible to 'disable' RootPOA somehow?
I don't think so + I don't think it would be any good (poas form a hierachy)
Well, I see at last one good thing about disabling or killing RootPOA
(assuming you can't change it's policies) -- it will remove necessity of
overriding _defaultPOA() method in every servant if you want all your
servants to belong to different POA :-)
--
Sincerely yours,
Michael.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.omniorb-support.com/pipermail/omniorb-list/attachments/20090321/fb423b53/attachment.htm
Duncan Grisby
2009-03-23 21:17:26 UTC
Permalink
On Friday 20 March, Michael Kilburn wrote:

[...]
Post by Michael Kilburn
Since our servants usually activated only in one POA and usually already
activated before possible _this() call -- this code 'saves' us. But there are
few cases when _this() might be called on non-active object -- and it behaves
as I feared (i.e. gets activated in RootPOA).
- I feel that this (probably helpful) behaviour is not standard-compliant --
can someone prove that it is not the case?
Like many things, it's a matter of interpretation. _this is defined in
the C++ mapping specification. In the 1.2 version of the mapping, in
section 4.40.2, it says:

"3. Outside the context of a request invocation on the target object
represented by the servant, it will return the object reference for a
servant that has already been activated, as long as the servant is
not incarnating multiple CORBA objects."

That's exactly what omniORB does.

However, that section then goes on to say

"This requires the POA with which the servant was activated to have
been created with the UNIQUE_ID and RETAIN policies. If the POA was
created with the MULTIPLE_ID or NON_RETAIN policies, the
PortableServer::WrongPolicy exception is thrown. The POA is gotten by
invoking _default_POA() on the servant."

Depending on how you read it, that may or may not override the earlier
bit. Once a servant is activated in one or more POAs, talking about the
one returned by _default_POA is rather nonsensical.

I think it could possibly be considered a bug that if a servant is
activated a single in a POA with the MULTIPLE_ID policy, a reference for
the single activation is returned, rather than it throwing an
exception. I do not, on the other hand, think it is a bug that it
returns a reference for the single activation if there is one, in the
case of a POA with the UNIQUE_ID policy, even if _default_POA returns a
different POA. omniORB is definitely not going to change in this
respect. To change it would break an enormous amount of code.
Post by Michael Kilburn
- is there any way to change RootPOA's policies? (to remove ecessity of
creating another POA)
- I am trying to avoid necessity of overriding _defaultPOA (someone will
forget to do it and it will lead to hard-to-find problems). So there any way
to ensure that all objects get activated in specific POA without this?
- maybe it is possible to 'disable' RootPOA somehow?
You can't do any of these things without modifying omniORB, I'm afraid.
One simple thing you could do would be to modify the
PortableServer::ServantBase class in include/omniORB4/poa.h to declare
that _default_POA() is abstract. That way all your servant classes would
have to define it.
Post by Michael Kilburn
I have created a ServantManager object and registered it with POA. According
to standard when object is activated _add_ref() is called nspecified number of
times. The question is how many times etherealize() method of ServantManager
should call _remove_ref() when called with remaining_activations = true? It
works with one call -- but is it guaranteed?
The spec is decidedly unclear on that point, but it must surely be the
intention. If that wasn't the case, application code would have to know
how many times the POA had called _add_ref(), which would be crazy.
Certainly in omniORB you should call it just once.

Cheers,

Duncan.
--
-- Duncan Grisby --
-- ***@grisby.org --
-- http://www.grisby.org --
Michael Kilburn
2009-03-25 11:24:08 UTC
Permalink
Post by Duncan Grisby
Like many things, it's a matter of interpretation. _this is defined in
the C++ mapping specification. In the 1.2 version of the mapping, in
Yes exactly this section I had in mind...
Post by Duncan Grisby
"3. Outside the context of a request invocation on the target object
represented by the servant, it will return the object reference for a
servant that has already been activated, as long as the servant is
not incarnating multiple CORBA objects."
That's exactly what omniORB does.
I see no point in checking number of activations then...
(activations_.size() == 1)
Post by Duncan Grisby
However, that section then goes on to say
"This requires the POA with which the servant was activated to have
been created with the UNIQUE_ID and RETAIN policies. If the POA was
created with the MULTIPLE_ID or NON_RETAIN policies, the
PortableServer::WrongPolicy exception is thrown. The POA is gotten by
invoking _default_POA() on the servant."
Depending on how you read it, that may or may not override the earlier
bit.
I would say second part does not override anything -- it just specifies how
that new reference should be created, i.e.:
- call _defaultPOA()
- check policies
- throw or duplicate a reference

though here is some amount of confusion -- which POA they refer to in "This
requires the POA with which the servant was activated to have"? if this is
POA where object is already activated -- it does not make sense in case if
object is activated in multiple POAs. If they mean _defaultPOA() -- they
worded it rather bad.
Post by Duncan Grisby
Once a servant is activated in one or more POAs, talking about the
one returned by _default_POA is rather nonsensical.
I see nothing nonsensical about this behaviour -- since given object is not
a target of the current request and user (instead of properly duplicating
existing reference) tries to create new reference without specifying POA --
default one will be used.
Post by Duncan Grisby
omniORB is definitely not going to change in this
respect. To change it would break an enormous amount of code.
:-) I knew it... I bet this enormous amount of code has the same problem we
do -- if for some reason _this() is called on deactivated object it will be
(unexpectedly) activated in the RootPOA.
Post by Duncan Grisby
The question is how many times etherealize() method of ServantManager
Post by Michael Kilburn
should call _remove_ref() when called with remaining_activations = true?
It
Post by Michael Kilburn
works with one call -- but is it guaranteed?
Certainly in omniORB you should call it just once.
Thanks!
--
Sincerely yours,
Michael.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.omniorb-support.com/pipermail/omniorb-list/attachments/20090325/0f520ed4/attachment.htm
Duncan Grisby
2009-03-25 16:28:17 UTC
Permalink
On Wednesday 25 March, Michael Kilburn wrote:

[...]
? "3. Outside the context of a request invocation on the target object
? represented by the servant, it will return the object reference for a
? servant that has already been activated, as long as the servant is
? not incarnating multiple CORBA objects."
That's exactly what omniORB does.
I see no point in checking number of activations then... (activations_.size()
== 1)
That's essential for the "as long as the servant is not incarnating
multiple CORBA objects" bit.
However, that section then goes on to say
?"This requires the POA with which the servant was activated to have
? been created with the UNIQUE_ID and RETAIN policies. If the POA was
? created with the MULTIPLE_ID or NON_RETAIN policies, the
? PortableServer::WrongPolicy exception is thrown. The POA is gotten by
? invoking _default_POA() on the servant."
Depending on how you read it, that may or may not override the earlier
bit.
I would say second part does not override anything -- it just specifies how
- call _defaultPOA()
- check policies
- throw or duplicate a reference
though here is some amount of confusion -- which POA they refer to in "This
requires the POA with which the servant was activated to have"? if this is POA
where object is already activated -- it does not make sense in case if object
is activated in multiple POAs. If they mean _defaultPOA() -- they worded it
rather bad.
"The POA with which the servant was activated" clearly means just what
it says -- if I activate a servant in a particular POA, that is the POA
in which it is activated, regardless of what the servant's _default_POA
method might return.

In this code

servant = new MyServantClass();
mypoa->activate_object(servant);

Which POA is the servant activated in? Clearly it's activated in
mypoa. Nobody has to ask what the servant's _default_POA method returns
to answer that question.

Now if I do

myobj = servant->_this();

Clearly my servant has a single activation in a single POA, so
(according to the rules quoted above) the call to _this() returns a
reference corresponding to that activation in that POA.
Once a servant is activated in one or more POAs, talking about the
one returned by _default_POA is rather nonsensical.
I see nothing nonsensical about this behaviour -- since given object is not a
target of the current request and user (instead of properly duplicating
existing reference) tries to create new reference without specifying POA --
default one will be used.
I think the confusion is around the intention of the _this() method.
_this() is not intended to return *a* reference corresponding to a
servant, it's intended to return *the* reference corresponding to a
servant. i.e. the one single reference that makes sense for a servant.
If a servant is activated once in one POA, that is clearly the reference
you want. If a servant is activated multiple times (regardless of
whether in just one POA or multiple POAs), there is no single correct
reference to return, so _this() throws an exception.

It's only in the case that a servant is not activated at all that the
question of "which POA?" arises. If you have to ask "which POA?", then
the answer is the one returned by _default_POA(). That's why it's called
default -- it's the one to use if you don't have any other POA to
choose.
omniORB is definitely not going to change in this
respect. To change it would break an enormous amount of code.
:-) I knew it... I bet this enormous amount of code has the same problem we do
-- if for some reason _this() is called on deactivated object it will be
(unexpectedly) activated in the RootPOA.
Yes, but it's not omniORB's job to protect you from all bugs in
application code. There is plenty of code out there that looks just like
the simple example I've used above, and that is trivially correct.

Cheers,

Duncan.
--
-- Duncan Grisby --
-- ***@grisby.org --
-- http://www.grisby.org --
Michael Kilburn
2009-03-26 06:12:11 UTC
Permalink
Post by Michael Kilburn
Post by Michael Kilburn
I see no point in checking number of activations then...
(activations_.size()
Post by Michael Kilburn
== 1)
That's essential for the "as long as the servant is not incarnating
multiple CORBA objects" bit.
Hmm... According to my understanding of terminology "CORBA object" is a
virtual entity described by an interface in idl file. Servant instance is an
incarnation of CORBA object (i.e. it implements given interface). When
servant implements multiple interfaces -- this is what called "incarnates
multiple CORBA objects". I.e. number of activations have nothing to do with
it. But I could be wrong, of course...


I think the confusion is around the intention of the _this() method.
Post by Michael Kilburn
_this() is not intended to return *a* reference corresponding to a
servant, it's intended to return *the* reference corresponding to a
servant. i.e. the one single reference that makes sense for a servant.
If a servant is activated once in one POA, that is clearly the reference
you want. If a servant is activated multiple times (regardless of
whether in just one POA or multiple POAs), there is no single correct
reference to return, so _this() throws an exception.
It's only in the case that a servant is not activated at all that the
question of "which POA?" arises. If you have to ask "which POA?", then
the answer is the one returned by _default_POA(). That's why it's called
default -- it's the one to use if you don't have any other POA to
choose.
All this is confusing and dangerous, even we we asume that there s no
logical problems in standard's wording... I would prefer simple and
straightforward approach -- if not current, then grab default POA, check
policies then return ref or throw.
Post by Michael Kilburn
Post by Michael Kilburn
:-) I knew it... I bet this enormous amount of code has the same problem
we do
Post by Michael Kilburn
-- if for some reason _this() is called on deactivated object it will be
(unexpectedly) activated in the RootPOA.
Yes, but it's not omniORB's job to protect you from all bugs in
application code. There is plenty of code out there that looks just like
the simple example I've used above, and that is trivially correct.
Majority of code probably does not create additional POAs (no POAs -- no
problems).
I do not try to tell that omniORB has to protect me from this, this is
standard's job -- just wanted to know why omniORB's behaviour is different
from what my eyes see in standard -- clearly there is at least one problem
in the document.
--
Sincerely yours,
Michael.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.omniorb-support.com/pipermail/omniorb-list/attachments/20090325/952b5b50/attachment.htm
Nigel Rantor
2009-03-26 16:31:08 UTC
Permalink
Post by Michael Kilburn
Post by Michael Kilburn
I see no point in checking number of activations then...
(activations_.size()
Post by Michael Kilburn
== 1)
That's essential for the "as long as the servant is not incarnating
multiple CORBA objects" bit.
Hmm... According to my understanding of terminology "CORBA object" is a
virtual entity described by an interface in idl file. Servant instance
is an incarnation of CORBA object (i.e. it implements given interface).
When servant implements multiple interfaces -- this is what called
"incarnates multiple CORBA objects". I.e. number of activations have
nothing to do with it. But I could be wrong, of course...
Hi Michael, I've been lurking this discussion.

A Servant may handle requests for multiple different Object instances.
This is what it means for a Servant to incarnate multiple Objects. It
has nothing to do with the number of different CORBA IDL interfaces that
a Servant implements.

For example you can use a ServantManager to always provide the exact
same Servant for every request, irrespective of the actual object
requested. Depending on what you're trying to achieve this can be very
useful.
Post by Michael Kilburn
I think the confusion is around the intention of the _this() method.
_this() is not intended to return *a* reference corresponding to a
servant, it's intended to return *the* reference corresponding to a
servant. i.e. the one single reference that makes sense for a servant.
If a servant is activated once in one POA, that is clearly the reference
you want. If a servant is activated multiple times (regardless of
whether in just one POA or multiple POAs), there is no single correct
reference to return, so _this() throws an exception.
It's only in the case that a servant is not activated at all that the
question of "which POA?" arises. If you have to ask "which POA?", then
the answer is the one returned by _default_POA(). That's why it's called
default -- it's the one to use if you don't have any other POA to
choose.
All this is confusing and dangerous, even we we asume that there s no
logical problems in standard's wording... I would prefer simple and
straightforward approach -- if not current, then grab default POA, check
policies then return ref or throw.
This seems to be a difference of opinion then. I agree with Duncan's
interpretation of the standard. Can you explain why the above does not
seem straightforward to you?
Post by Michael Kilburn
Post by Michael Kilburn
:-) I knew it... I bet this enormous amount of code has the same
problem we do
Post by Michael Kilburn
-- if for some reason _this() is called on deactivated object it
will be
Post by Michael Kilburn
(unexpectedly) activated in the RootPOA.
Yes, but it's not omniORB's job to protect you from all bugs in
application code. There is plenty of code out there that looks just like
the simple example I've used above, and that is trivially correct.
Majority of code probably does not create additional POAs (no POAs -- no
problems).
I disagree with this. I can't recall a CORBA app where I've not created
at least one of my own POAs, simply becasue the default policy on the
RootPOA is normally not what you want.
Post by Michael Kilburn
I do not try to tell that omniORB has to protect me from this, this is
standard's job -- just wanted to know why omniORB's behaviour is
different from what my eyes see in standard -- clearly there is at least
one problem in the document.
As above, I think this is opinion then. You interpret the spec one way.
Other people interpret it in a different way. How about checking out
other vendor's implementations/interpretations?

Regards,

Nigel
Michael
2009-03-26 21:59:52 UTC
Permalink
I totally agree with Nigel, in six years of using CORBA I never wrote a
server application that didn't create its own POAs. No offense, but
quite frankly I think that argument is flawed ("we are the only ones
writing complicated software and one day it will hit us"). This is
exactly why you need coding guide lines. So, if you're concerned that
people will break code by using _this in the wrong way, enforce the
usage of a wrapper function that throws when _this is called on an
inactive object. Make that an inline function and the performance
penalty will be neglectable. You can then include a check for "_this" in
your QA process (e.g. grep "_this" *.C *.h). Quite simple. It's pretty
much like every piece of code, people will make mistakes, as a project
leader/manager it is your responsibility to define best practices and
setup a QA process. Especially in C++ it's all about your people not
doing stupid things (like enforcing use of smart pointers, RAII
principle etc.). Developers will always find ways to break code. Did you
ever consider using a different Middleware/RPC solution, because the
CORBA C++ mapping is pretty complicated (once you master it it's simple,
but from my experience training people is a nightmare)? I would never
again setup a project based on CORBA if I knew that many developers will
have to maintain the codebase.

just my 2 cents :)
michael
Post by Nigel Rantor
Post by Michael Kilburn
Post by Michael Kilburn
I see no point in checking number of activations then...
(activations_.size()
Post by Michael Kilburn
== 1)
That's essential for the "as long as the servant is not incarnating
multiple CORBA objects" bit.
Hmm... According to my understanding of terminology "CORBA object" is
a virtual entity described by an interface in idl file. Servant
instance is an incarnation of CORBA object (i.e. it implements given
interface). When servant implements multiple interfaces -- this is
what called "incarnates multiple CORBA objects". I.e. number of
activations have nothing to do with it. But I could be wrong, of
course...
Hi Michael, I've been lurking this discussion.
A Servant may handle requests for multiple different Object instances.
This is what it means for a Servant to incarnate multiple Objects. It
has nothing to do with the number of different CORBA IDL interfaces that
a Servant implements.
For example you can use a ServantManager to always provide the exact
same Servant for every request, irrespective of the actual object
requested. Depending on what you're trying to achieve this can be very
useful.
Post by Michael Kilburn
I think the confusion is around the intention of the _this() method.
_this() is not intended to return *a* reference corresponding to a
servant, it's intended to return *the* reference corresponding to a
servant. i.e. the one single reference that makes sense for a servant.
If a servant is activated once in one POA, that is clearly the reference
you want. If a servant is activated multiple times (regardless of
whether in just one POA or multiple POAs), there is no single correct
reference to return, so _this() throws an exception.
It's only in the case that a servant is not activated at all that the
question of "which POA?" arises. If you have to ask "which POA?", then
the answer is the one returned by _default_POA(). That's why it's called
default -- it's the one to use if you don't have any other POA to
choose.
All this is confusing and dangerous, even we we asume that there s no
logical problems in standard's wording... I would prefer simple and
straightforward approach -- if not current, then grab default POA,
check policies then return ref or throw.
This seems to be a difference of opinion then. I agree with Duncan's
interpretation of the standard. Can you explain why the above does not
seem straightforward to you?
Post by Michael Kilburn
Post by Michael Kilburn
:-) I knew it... I bet this enormous amount of code has the same
problem we do
Post by Michael Kilburn
-- if for some reason _this() is called on deactivated object it
will be
Post by Michael Kilburn
(unexpectedly) activated in the RootPOA.
Yes, but it's not omniORB's job to protect you from all bugs in
application code. There is plenty of code out there that looks just like
the simple example I've used above, and that is trivially correct.
Majority of code probably does not create additional POAs (no POAs -- no
problems).
I disagree with this. I can't recall a CORBA app where I've not created
at least one of my own POAs, simply becasue the default policy on the
RootPOA is normally not what you want.
Post by Michael Kilburn
I do not try to tell that omniORB has to protect me from this, this is
standard's job -- just wanted to know why omniORB's behaviour is
different from what my eyes see in standard -- clearly there is at
least one problem in the document.
As above, I think this is opinion then. You interpret the spec one way.
Other people interpret it in a different way. How about checking out
other vendor's implementations/interpretations?
Regards,
Nigel
_______________________________________________
omniORB-list mailing list
http://www.omniorb-support.com/mailman/listinfo/omniorb-list
Martin Trappel
2009-03-27 16:36:58 UTC
Permalink
(...) Developers will always find ways to break code. Did you
ever consider using a different Middleware/RPC solution, because the
CORBA C++ mapping is pretty complicated (once you master it it's simple,
but from my experience training people is a nightmare)? I would never
again setup a project based on CORBA if I knew that many developers will
have to maintain the codebase.
Drifting OT ... but interesting statement: Because it really raises the
question as to what else you'd like to use? It's not that there are that
many alternatives in the area where one uses C++/CORBA , or are there?

cheers,
Martin
Nigel Rantor
2009-03-27 17:33:29 UTC
Permalink
Post by Martin Trappel
(...) Developers will always find ways to break code. Did you
ever consider using a different Middleware/RPC solution, because the
CORBA C++ mapping is pretty complicated (once you master it it's simple,
but from my experience training people is a nightmare)? I would never
again setup a project based on CORBA if I knew that many developers will
have to maintain the codebase.
Drifting OT ... but interesting statement: Because it really raises the
question as to what else you'd like to use? It's not that there are that
many alternatives in the area where one uses C++/CORBA , or are there?
ICE - http://zeroc.com/
Kevin Bailey
2009-03-27 23:07:06 UTC
Permalink
Post by Nigel Rantor
ICE - http://zeroc.com/
That's just CORBA done the way if Henning were king, right ?
Nigel Rantor
2009-03-27 23:21:46 UTC
Permalink
Post by Kevin Bailey
Post by Nigel Rantor
ICE - http://zeroc.com/
That's just CORBA done the way if Henning were king, right ?
I think that's somewhat of an oversimplification.

Especially seeing as one of the things he said he would not do is
OBV...and now they do OBV...but, anyway.

One of the things that is nice about the mapping is that they have had
the benefit of seeing what worked and what didn't with CORBA, especially
w.r.t the language mapping for C++.

Also, C++ has moved on a lot since the original CORBA mapping, and it
shows when you compare the two. For example, the STL is used for
sequences, as you might expect if you didn't know how old the CORBA/C++
mapping was.

So, yes and no. Let's not oversimplify.

Disclaimer - I have never used Ice on a "real" project yet, I always
provide my employers with the honest answer and when they see the
license fee Ice vs no license fee FOSS CORBA I get to use CORBA...

Regards,

n
Michael Kilburn
2009-03-31 12:36:35 UTC
Permalink
Post by Michael
I totally agree with Nigel, in six years of using CORBA I never wrote a
server application that didn't create its own POAs. No offense, but
quite frankly I think that argument is flawed ("we are the only ones
writing complicated software and one day it will hit us"). This is
exactly why you need coding guide lines. So, if you're concerned that
people will break code by using _this in the wrong way, enforce the
usage of a wrapper function that throws when _this is called on an
inactive object. Make that an inline function and the performance
penalty will be neglectable.
Oh, that is for sure... I'll try to invent some C++ mechanism that will make
it harder to break.


You can then include a check for "_this" in
Post by Michael
your QA process (e.g. grep "_this" *.C *.h).
Our "QA process" would surprise you :-D . Essentially it is absent. entire
product is single threaded, well divided in parts and people working on it
are experienced C++ developers, those that learn are under close supervision
(but most of them are not particlarly exposed to every intricacy of CORBA,
esp considering that we switched from Orbacus to omniORB quite recently --
it took ~six month of work, and I had to learn CORBA in a very short time).
Post by Michael
Quite simple. It's pretty
much like every piece of code, people will make mistakes, as a project
leader/manager it is your responsibility to define best practices and
setup a QA process.
I disagree -- it turned out that _this()'s behaviour is quite twisted... One
thing when developer screws with nicely designed framework or library and
another one -- when he steps on rakes of something like _this(). (pun
intended :) )
Post by Michael
Especially in C++ it's all about your people not
doing stupid things (like enforcing use of smart pointers, RAII
principle etc.). Developers will always find ways to break code.
No, if they are experienced and tools they are using well-thought out and
well-designed.
Post by Michael
Did you
ever consider using a different Middleware/RPC solution, because the
CORBA C++ mapping is pretty complicated (once you master it it's simple,
but from my experience training people is a nightmare)?
Agree, CORBA keeps surprising me... And after all I've learned I am not sure
that CORBA is a necessary a good thing -- it's complexity, myriad of
non-obvious details outweight many of it's benefits. I am sure those who
make decisions on that level considered other alternatives to CORBA, but
risks & costs of switching to something else are (probably) in CORBA's
favor.


I would never
Post by Michael
again setup a project based on CORBA if I knew that many developers will
have to maintain the codebase.
:-) Sorry, it won't work here -- we have a very large in-house product that
is under constant development for last 10 (or maybe 15?) years. About every
month or two we have a new release. People come and go regularly, and I am
just one of them. We are saved by the fact that product is single-threaded
(on purpose) and not many want to touch communication layer (that uses
CORBA)...
--
Sincerely yours,
Michael.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.omniorb-support.com/pipermail/omniorb-list/attachments/20090331/b8ac1d43/attachment.htm
Michael
2009-03-31 16:11:48 UTC
Permalink
...
Post by Michael Kilburn
Post by Michael
Quite simple. It's pretty
much like every piece of code, people will make mistakes, as a project
leader/manager it is your responsibility to define best practices and
setup a QA process.
I disagree -- it turned out that _this()'s behaviour is quite twisted... One
thing when developer screws with nicely designed framework or library and
another one -- when he steps on rakes of something like _this(). (pun
intended :) )
That's why I think somebody has to maintain best practices/wrappers - to
avoid having everybody learn every twisted detail and have to do every
mistake on their own (mistake doesn't mean somebody is a bad developer,
there are just non-obvious problems, and the CORBA specification is not
what I would call a nicely designed framework).
...
Post by Michael Kilburn
No, if they are experienced and tools they are using well-thought out and
well-designed.
That sounds a little naive to me, but maybe I'm just a cynical person :)

...
Post by Michael Kilburn
:-) Sorry, it won't work here -- we have a very large in-house product that
is under constant development for last 10 (or maybe 15?) years. About every
month or two we have a new release. People come and go regularly, and I am
just one of them. We are saved by the fact that product is single-threaded
(on purpose) and not many want to touch communication layer (that uses
CORBA)...
Hmmm, now I'm really curious what product you're actually working on...
Michael Kilburn
2009-04-01 12:01:57 UTC
Permalink
Post by Michael Kilburn
Post by Michael Kilburn
:-) Sorry, it won't work here -- we have a very large in-house product
that
Post by Michael Kilburn
is under constant development for last 10 (or maybe 15?) years. About
every
Post by Michael Kilburn
month or two we have a new release. People come and go regularly, and I
am
Post by Michael Kilburn
just one of them. We are saved by the fact that product is
single-threaded
Post by Michael Kilburn
(on purpose) and not many want to touch communication layer (that uses
CORBA)...
Hmmm, now I'm really curious what product you're actually working on...
Bit off-topic...

It is deals & risk management system in investment bank -- essentially huge
CORBA server (idl's are measured in megabytes) + various frontends (python,
.NET, VB) (answer to obvious question -- we are doing very well in this time
of crisis, esp in comparison with Wall Street :-D) Funniest poroblem --
people keep adding new functionality (it is easy), but to change or fix
existing one -- equivalent of open heart surgery
--
Sincerely yours,
Michael.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.omniorb-support.com/pipermail/omniorb-list/attachments/20090401/50d4c36a/attachment.htm
Michael Kilburn
2009-03-31 12:16:57 UTC
Permalink
Post by Michael Kilburn
All this is confusing and dangerous, even we we asume that there s no
Post by Michael Kilburn
logical problems in standard's wording... I would prefer simple and
straightforward approach -- if not current, then grab default POA, check
policies then return ref or throw.
This seems to be a difference of opinion then. I agree with Duncan's
interpretation of the standard. Can you explain why the above does not seem
straightforward to you?
-- see below --

I do not try to tell that omniORB has to protect me from this, this is
Post by Michael Kilburn
Post by Michael Kilburn
standard's job -- just wanted to know why omniORB's behaviour is different
from what my eyes see in standard -- clearly there is at least one problem
in the document.
As above, I think this is opinion then. You interpret the spec one way.
Other people interpret it in a different way. How about checking out other
vendor's implementations/interpretations?
Standard should be unambiguous source of truth (if it is not -- this is a
holy scripture then :-) ). Here is the piece from C+ mappings 4.40.2.p3:

Outside the context of a request invocation on the target object represented
by the servant, it will return the object reference for a servant that has
already been activated, as long as the servant is not incarnating multiple
CORBA objects. This requires *[* the POA with which the servant was
activated *]* to have been created with the UNIQUE_ID and RETAIN policies.
If the POA was created with the MULTIPLE_ID or NON_RETAIN policies, the
PortableServer::WrongPolicy exception is thrown. *[*The POA is gotten by
invoking _default_POA() on the servant. *]*

I selected pieces of interest with *[* *]*. If you'd say that this is not
confusing at all and clear as day -- I'll go and check my mental health with
my doctor. Of course, you can have "an interpretation" but it is as useful
as any other interpretation, if text is not clear.

E.g. I am used to reading from right to left :-) therefore for me we are
supposed to get default_POA, check policies and then either throw or
duplicate a reference. And it seems to me way simpler and obvious than
behaviour expressed by omniORB, which is far from being obvious and
predictable at the place where you invoke _this().

The wording used by standard seems to suggest that _defaultPOA() is supposed
to return POA servant was activated in... But no clear details (to me). :(
--
Sincerely yours,
Michael.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.omniorb-support.com/pipermail/omniorb-list/attachments/20090331/6b81a333/attachment.htm
Duncan Grisby
2009-03-26 20:49:20 UTC
Permalink
Post by Michael Kilburn
Hmm... According to my understanding of terminology "CORBA object" is a
virtual entity described by an interface in idl file. Servant instance is an
incarnation of CORBA object (i.e. it implements given interface). When servant
implements multiple interfaces -- this is what called "incarnates multiple
CORBA objects". I.e. number of activations have nothing to do with it. But I
could be wrong, of course...
That explains the confusion -- your terminology is not quite right.

A _CORBA object_ is a logical entity.

Each object has an _interface_ that describes the operations it
supports.

An object has a single interface; any number of objects can have the
same interface.

The only way to access an object is through an _object reference_.

An object reference refers to just one object; multiple object
references can refer to the same object.

Objects are made available by _servers_. Servers can provide an
arbitrary number of objects.

Servers map CORBA objects to programming language constructs with
_object adapters_. The Portable Object Adapter (POA) is the standard
object adapter definition.

A _servant_ is a programming language object.

A servant is implemented by a _servant class_. A servant class
implements a single CORBA interface. A servant class may not implement
more than one interface. [Note to pedants: I'm ignoring DSI here.]

When an object adapter maps a CORBA object to a servant, the servant is
said to _incarnate_ the CORBA object.

A single servant can incarnate any number of CORBA objects, but they
must all have the same interface.

To statically map a CORBA object to a servant, you _activate_ the
servant. Activating a servant causes it to incarnate the corresponding
object. Other POA policies allow objects to be incarnated on demand.


All of this is described quite well in the CORBA spec, especially the
chapter on the POA.

Cheers,

Duncan.
--
-- Duncan Grisby --
-- ***@grisby.org --
-- http://www.grisby.org --
Michael Kilburn
2009-03-31 11:57:20 UTC
Permalink
Post by Duncan Grisby
That explains the confusion -- your terminology is not quite right.
A _CORBA object_ is a logical entity.
[long (and frankly speaking quite useful) info on CORBA basics]

Thanks, Duncan! I was delaying my answer to you in hope that I get some time
to dig in standard... But it looks like it is not going to happen soon
enough (a bit swamped with other stuff) and quite likely my findings will
support your point of view anyway. So, I'll leave it on my 'todo list' and
will tell you:

Thanks for help!!!

Is there any easy way to check whether given servant is activated in given
POA? (apart of calling servant_to_reference() function and catching
exception)
--
Sincerely yours,
Michael.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.omniorb-support.com/pipermail/omniorb-list/attachments/20090331/134944c8/attachment.htm
Michael
2009-03-31 16:00:50 UTC
Permalink
The only method I'm aware of is calling reference_to_servant and catch
Post by Michael Kilburn
Post by Duncan Grisby
That explains the confusion -- your terminology is not quite right.
A _CORBA object_ is a logical entity.
[long (and frankly speaking quite useful) info on CORBA basics]
Thanks, Duncan! I was delaying my answer to you in hope that I get some time
to dig in standard... But it looks like it is not going to happen soon
enough (a bit swamped with other stuff) and quite likely my findings will
support your point of view anyway. So, I'll leave it on my 'todo list' and
Thanks for help!!!
Is there any easy way to check whether given servant is activated in given
POA? (apart of calling servant_to_reference() function and catching
exception)
------------------------------------------------------------------------
_______________________________________________
omniORB-list mailing list
http://www.omniorb-support.com/mailman/listinfo/omniorb-list
Michael
2009-03-31 16:01:10 UTC
Permalink
PortableServer::Servant servant = _poa->reference_to_servant(obj);
servant->_remove_ref();
Post by Michael Kilburn
Post by Duncan Grisby
That explains the confusion -- your terminology is not quite right.
A _CORBA object_ is a logical entity.
[long (and frankly speaking quite useful) info on CORBA basics]
Thanks, Duncan! I was delaying my answer to you in hope that I get some time
to dig in standard... But it looks like it is not going to happen soon
enough (a bit swamped with other stuff) and quite likely my findings will
support your point of view anyway. So, I'll leave it on my 'todo list' and
Thanks for help!!!
Is there any easy way to check whether given servant is activated in given
POA? (apart of calling servant_to_reference() function and catching
exception)
------------------------------------------------------------------------
_______________________________________________
omniORB-list mailing list
http://www.omniorb-support.com/mailman/listinfo/omniorb-list
Michael Kilburn
2009-04-01 11:54:38 UTC
Permalink
Post by Michael
PortableServer::Servant servant = _poa->reference_to_servant(obj);
servant->_remove_ref();
Just being pedantic... this is better:

PortableServer::Servant_var servant = _poa->reference_to_servant(obj);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.omniorb-support.com/pipermail/omniorb-list/attachments/20090401/f81d8459/attachment.htm
Michael
2009-04-01 13:01:47 UTC
Permalink
Post by Michael Kilburn
Post by Michael
PortableServer::Servant servant = _poa->reference_to_servant(obj);
servant->_remove_ref();
PortableServer::Servant_var servant = _poa->reference_to_servant(obj);
Sorry, but no :) PortableServer::Servant is a pointer to (not a copy of)
the incarnating servant in the active object map. You don't want the
_var class to clean that up ever (and btw it won't compile anyway
because PortableServer::Servant is a local corba pseudo class thingy).
You're confused about memory management rules here (which brings me back
to my previous argument about CORBA complexity and developers getting
confused about it :).

So you understand the context:
try
{
PortableServer::Servant servant = _poa->reference_to_servant(obj);
servant->_remove_ref();
IRObject_impl* impl = dynamic_cast<IRObject_impl*>(servant);
if (impl)
{
// do something
}
// there is no delete statement here, try this to crash it:
// delete servant;
}
catch(...)
{
// damn
}

This code does not lose any memory(!)
Note that reference_to_servant returns a pointer to a local servant
object, not a CORBA object reference (the servant returned could be also
a default servant (not sure if you ever worked with those) so you will
get a pointer to the default servant for every obj passed (because all
objects are backed by the same servant). That's why it is called
reference_to_servant :).
Duncan Grisby
2009-04-01 17:46:44 UTC
Permalink
Post by Michael
Post by Michael Kilburn
Post by Michael
PortableServer::Servant servant = _poa->reference_to_servant(obj);
servant->_remove_ref();
PortableServer::Servant_var servant = _poa->reference_to_servant(obj);
Sorry, but no :) PortableServer::Servant is a pointer to (not a copy of)
the incarnating servant in the active object map. You don't want the
_var class to clean that up ever (and btw it won't compile anyway
because PortableServer::Servant is a local corba pseudo class thingy).
You're both wrong, just in different ways :-)

The code with Servant_var won't compile, but that's because Servant_var
is a template, not because it's wrong to use a _var type with a
servant. This code is completely valid and does the right thing with
_remove_ref:

PortableServer::ServantBase_var servant = _poa->reference_to_servant(obj);
Post by Michael
You're confused about memory management rules here (which brings me back
to my previous argument about CORBA complexity and developers getting
confused about it :).
try
{
PortableServer::Servant servant = _poa->reference_to_servant(obj);
servant->_remove_ref();
That is a dangerous thing to do. By calling _remove_ref there, you are
assuming that the POA is going to keep holding its reference to the
servant. If another thread deactivates the object, you might find the
servant being deleted from under you. It's much safer to call
_remove_ref once you've finished using the servant, and the easiest way
to do that is to use ServantBase_var.
Post by Michael
IRObject_impl* impl = dynamic_cast<IRObject_impl*>(servant);
if (impl)
{
// do something
}
// delete servant;
A delete of the servant there is wrong because the POA still holds a
reference to the servant.

Cheers,

Duncan.
--
-- Duncan Grisby --
-- ***@grisby.org --
-- http://www.grisby.org --
Michael
2009-04-01 18:00:45 UTC
Permalink
Post by Duncan Grisby
Post by Michael
Post by Michael Kilburn
Post by Michael
PortableServer::Servant servant = _poa->reference_to_servant(obj);
servant->_remove_ref();
PortableServer::Servant_var servant = _poa->reference_to_servant(obj);
Sorry, but no :) PortableServer::Servant is a pointer to (not a copy of)
the incarnating servant in the active object map. You don't want the
_var class to clean that up ever (and btw it won't compile anyway
because PortableServer::Servant is a local corba pseudo class thingy).
You're both wrong, just in different ways :-)
The code with Servant_var won't compile, but that's because Servant_var
is a template, not because it's wrong to use a _var type with a
servant. This code is completely valid and does the right thing with
PortableServer::ServantBase_var servant = _poa->reference_to_servant(obj);
Sometimes I love CORBA :). I never thought of that in the first place,
because I really need the dynamic cast. Without checking the specs, how
would I do a dynamic cast from a PortableServer::ServantBase_var?
(I would assume
whatever_impl* that = dynamic_cast<whatever_impl*>(servant.in()))
Post by Duncan Grisby
Post by Michael
You're confused about memory management rules here (which brings me back
to my previous argument about CORBA complexity and developers getting
confused about it :).
And obviously sometimes that includes me as well :)
Post by Duncan Grisby
Post by Michael
try
{
PortableServer::Servant servant = _poa->reference_to_servant(obj);
servant->_remove_ref();
That is a dangerous thing to do. By calling _remove_ref there, you are
assuming that the POA is going to keep holding its reference to the
servant. If another thread deactivates the object, you might find the
servant being deleted from under you. It's much safer to call
_remove_ref once you've finished using the servant, and the easiest way
to do that is to use ServantBase_var.
Actually in my case it is not, but that's because I copy and pasted that
out of code that works differntly anyway (I use a combined approach, so
the pointer is "safe" because it is backed by a smart pointer somewhere
else). Of course, I shouldn't advise that without comments because
you're right that without these specifics it is extremely dangerous.
Knowing that _var works, I think I will change my code anyway, since it
seems more maintenance-friendly.
Post by Duncan Grisby
Post by Michael
IRObject_impl* impl = dynamic_cast<IRObject_impl*>(servant);
if (impl)
{
// do something
}
// delete servant;
A delete of the servant there is wrong because the POA still holds a
reference to the servant.
That's what I wanted to point out (but the argument was flawed in the
first place anyway)
Post by Duncan Grisby
Cheers,
Duncan.
Michael Kilburn
2009-04-02 13:10:53 UTC
Permalink
Post by Duncan Grisby
Post by Michael
Post by Michael Kilburn
PortableServer::Servant_var servant = _poa->reference_to_servant(obj);
Sorry, but no :) PortableServer::Servant is a pointer to (not a copy of)
the incarnating servant in the active object map. You don't want the
_var class to clean that up ever (and btw it won't compile anyway
because PortableServer::Servant is a local corba pseudo class thingy).
You're both wrong, just in different ways :-)
Duh, of course I meant ServantBase_var... :-) Forgot a bit details, since we
have it wrapped in a macro.
Post by Duncan Grisby
PortableServer::Servant servant = _poa->reference_to_servant(obj);
Post by Michael
servant->_remove_ref();
That is a dangerous thing to do. By calling _remove_ref there, you are
assuming that the POA is going to keep holding its reference to the
servant.
:-) This is exactly what happens in our case... But I am well-aware about
it.
--
Sincerely yours,
Michael.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.omniorb-support.com/pipermail/omniorb-list/attachments/20090402/b5d79e6f/attachment.htm
Loading...