Re: Exception handling revisited

From: Matthew D. Langston (langston@SLAC.stanford.edu)
Date: Thu Nov 04 1999 - 21:34:28 MET


Hi John,

There are two issues involved with exceptions and ROOT.  You've
identified one of them, which is getting rudimentary support for
exceptions to "Do the Right Thing" with regards to the
interpreter/compiled-code barrier.  The other issue is exception safety
w.r.t. the ROOT libraries themselves.

Both of your proposed solutions address the first issue, and sound
reasonable to me (i.e. both your "stop-gap" solution and your "elegant"
solution).

I experimented with ROOT and exceptions in the past (I believe it was
with ROOT 2.22.x) and I made local changes to the ROOT source similar to
what you are proposing (I used function try blocks instead of just try
blocks).  This "worked" for me, but I quickly found that the ROOT
libraries themselves weren't exception safe.  In particular I found
several instances when an exception propagating through parts of the
ROOT libraries would corrupt the local state of ROOT objects.  As you
may know, this is typical of libraries that haven't been designed for
exception safety, and so is not just particular to ROOT.

Perhaps ROOT 2.23.x is exception safe, but I haven't checked.  There is
nothing in the ROOT Release Notes about an exception audit, so I doubt
that this issue has been addressed yet.  Until it is, I would just offer
a general warning that if users use exceptions with ROOT, then they
should insure that exceptions not propagate through any part of the ROOT
libraries.  If they do, there are two possibilities:

  1) The state of all ROOT objects is good.
  2) The state of some or all ROOT objects are corrupt.

The trouble is, you can't know unless you have looked at the ROOT
source.

--
Matthew D. Langston
SLD, Stanford Linear Accelerator Center
langston@SLAC.Stanford.EDU


John Zweizig wrote:
> 
> I'd like to revisit a previous the root-talk thread on exception
> handling. In that thread one root user pointed out that any exception
> thrown by a compiled function will cause root to terminate. I have just
> run into the same problem and I agree that this is an unusually annoying
> feature. At the time of the previous thread, there were two responses, one
> from Fons and the other from Masa as follows:
>   1) Fons added some code to TSystem::Run() which attempted to catch
>      exceptions at that level and restart the application. This doesn't
>      work for compiled functions called by the interpreter. I believe that
>      the reason it doesn't work is that CINT is written/compiled in C, so
>      the exceptions can't propagate up the stack past CINT.
> 
>   2) Masa stated that problems implicit in the C++ definition make it
>      impossible to catch exceptions from compiled functions in the
>      interpreter.
> 
> I think that in fact what is needed is not the handling of the exceptions
> per se, but rather some stop-gap to prevent root from terminating if an
> exception is thrown by a compiled function being interpreted. I believe
> that this is possible and that it can be implemented in one of two ways.
> 
> The most trivial way would be to put an additional layer between cint and
> the compiled function, as follows:
> 
> Right now Cint call compiled C++ functions in
> 
> int G__call_cppfunc(...) {
>      --- stuff snipped ---
>         (*cppfun)(...);
>      --- stuff snipped
> }
> 
> The additional C++ layer  could be added as follows:
> 
> int G__call_cppfunc(...) {
>     --- stuff snipped ---
>     if (G__cpp_stopgap(cppfun, ...)) {
>         ---- function failed... stop interpreting ---
>     }
>     --- stuff snipped
> }
> 
> where G__cpp_stopgap must be a C++ function like:
> 
> extern "C" {
> typedef int (cppwrap)(G__value*, char*, G__param*, int);
> 
> int
> G__cpp_stopgap(cppwrap* cppfunc, G__value* a, char* b, G__param* c, int d) {
>     try {
>         (*cppfunc)(a, b, c, d);
>         return 0;
>     } catch (...) {
>         return 1;
>     }
> }
> }
> 
> A more elegant way of handling the exceptions would be to put the
> try...catch  code into the cint wrappers themselves based on the throw()
> clause of the function definition.



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:42 MET