COM/CORBA/DCOP (was: Hello people. I have some questions)

Alex Martelli aleax at aleax.it
Fri Sep 7 15:24:05 CEST 2001


"Neil Hodgson" <nhodgson at bigpond.net.au> wrote in message
news:_Q2m7.21724$bY5.123263 at news-server.bigpond.net.au...
> Alex Martelli:
>
> > Sure, it's the same as passing an invalid pointer, except that it must
be
> > diagnosed by a different HRESULT -- that's what E_POINTER is *FOR*, you
> > know.  In either case, crashing (technically, "propagating an
> exception" --
> > remember "crashes" are really exceptions in NT's SEH model) is NOT
> > permitted.
>
>    This is a nice interpretation of the COM spec (referenced later in your
> reply) but unfortunately it is an incorrect interpretation. Exception here

It's not an interpretation, it's the literal text of the COM specs.

> is referring to C++ exceptions rather than SEH or crashing. No COM server

It specifically mentions that different languages have different
concept of exceptions, so whence comes your *interpretation* that
it is specific to C++ when it's explicitly saying the opposite?

> code I've ever seen has verified pointer correctness in release builds
> (sometimes pointer verification is done in debug build traces) as it would
> impose too much of a performance impact.

My COM server code always satisfies the letter of the spec (except
when it has bugs -- but I don't introduce bugs deliberately:-).  SEH
is normally handiest: rather than verirying pointer-correctness myself,
let the hardware do it for me with a little help from the OS.  As
usual, doing things right isn't that much harder than doing them
sloppily or incorrectly.

>    To demonstrate that this is the case for at least some COM servers,
here

There's no real need to demonstrate that buggy code exists (in
particular, that buggy code exists in some Microsoft products): I
think we can all take you on faith regarding this point, even
though of course we've NEVER seen Microsoft release buggy code
(well, hardly ever).

>    The three mentioned ProgIDs were the first I tried and I'd expect every
> server on the machine to crash with this provocation. You'll also see
other
> interfaces that take pointers will crash when fed random pointers.

Random (output) pointers will likely cause _your_ (calling) code to crash
soon after, of course: the first time you pass a pointer that happens
to be to some writable area of your address space, which gets correctly
overwritten by the interface whose method you have called, it's your
lookout.  But it's so easy for the server's author to use SEH to
make sure the *server's* code respects the COM specs (doesn't propagate
the exception to your calling code, but rather returns an appropriate
HRESULT) that there's no excuse for not doing so.


> >...  Say a client calls your Invoke with a standard
> > dispatch-ID such as -4, just trying to find out whether your interface
can
> > be enumerated (==can supply an IEnumVariant*) -- this is perfectly OK
> > behavior by an Automation client, by the way.  If you don't check the
> > dispID, you may well end up addressing a vtable with an out-of-bounds
> > negative index, and get a "random" (sort-of) procedure address to
dispatch
> > to.  ...
>
>    I'm almost ready to agree on this one but the documentation doesn't
> really give clients a lot of freedom: "Use GetIDsOfNames or the object's
> documentation to obtain the dispatch identifier. ".

There is *NO* name which ensures the standard DISPID_NEWENUM will be
returned by GetIDsOfNames (in the context of _collections_, only,
the name "_NewEnum" is designated for that -- but it's to be marked
as *restricted*, so it's *NOT* going to be returned by GetIDsOfNames
in a compliant implementation!).  Microsoft has not designated any
specific *names* duplicating the purposes of the various DISPID_NEWENUM,
DISPID_VALUE (the default-property of an Automation object, if any),
and so on, which it *has* reserved and designated.

> Yes, it is bad
> engineering to not validate dispatch IDs but an interface contract has two
> sides.

Three, since the framework's specs can be seen as a third, impartial
side.  And they specify (e.g) that DISPID_NEWENUM (-4, as it happens)
is THE way a client can (try to) access _NewEnum -- DISPID_VALUE is
THE way a client can (try to) access the default property for the
object, for which NO standard name is even mentioned anywhere (and
indeed the name of said default properties, for objects that do
have a default property, does vary all over the place), and so on.

In the abstract, you could make a case that a function must not
waste effort trying to validate its preconditions -- that's not
the function's job.  Meyers is as hot as usual in defending this
stance in his PbC materials.  But, here, we're talking about a
framework which HAS specs -- maybe good ones, maybe bad ones,
but specs nevertheless.  If you claim to release a product that
supports that framework, then, by my light, it must first meet
the fw specs.  It's OK to have a variant version of the product,
or one which takes environment or registry switches or whatever,
to *violate* the specs in order to get better performance, or
functionality, etc, etc, if the client is also aware of or at
least unaffected by the violations -- I'm not a purist and I do
not insist that any (e.g.) C++ compiler MUST compile by ISO C++
standard *by default* (I *DO* insist that there IS a way to get
default behavior, and not an unreasonably inaccessible one -- or,
well, I WOULD insist on that if ANY product on the market could
give me 100% ISO C++ standard behavior, but that's another story:-).


> My habit of reading specs, particularly COM specs, extremely
> literally, come from suffering far too much grief at the hands of code
> (often written in Redmond) that works in an unreasonable but valid way. If
> the spec says "should", then it didn't say "must" and so you should not
rely
> on that section being followed.

That's how a well-written spec ought to be, yes, and it IS a good
thing to be generous in what you accept (and strict in what you
give out) whenever you can possibly afford that.  But the following
specs ARE just as unambiguous as any I've ever seen:

"""
In short, it is strictly illegal to throw an exception across an interface
invocation; all such cross-interface exceptions which are thrown are in fact
bugs in the offending interface implementation. Why have such a policy? The
first, straightforward, pragmatic reason is the technical reality that there
simply isn’t an ubiquitous exception model or semantic that is broadly
supported across languages and operating systems that one could choose to
permit
"""

What part of "strictly illegal" do you not understand?  What part of
"are in fact bugs in the ... implementation"?  And PLEASE note the
very clear (explanatory, but since we're quibbling on what "exceptions"
mean that's OK:-) mention of cross-language and cross-operating
system issues: NT-SEH exceptions (aka crashes), C++ exceptions, Java
exceptions, whatever, you just *DON'T* throw them across COM interfaces,
*NO MATTER WHAT*.  As the quoted section goes on to explain, you
return an appropriate HRESULT instead.  No excuses are allowed by
this section of the COM specs, nor do other docs override this one...


Alex






More information about the Python-list mailing list