EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

2002  2003  2004  2005  <20062007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 2002  2003  2004  2005  <20062007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: C++ Exceptions from CAC-UDP on exit
From: Andrew Johnson <[email protected]>
To: Jeff Hill <[email protected]>
Cc: "'EPICS core-talk'" <[email protected]>
Date: Wed, 20 Dec 2006 10:25:58 -0600
Hi Jeff,

Mystery solved, suggested fix below.

I caught another of those exceptions on linux-x86 (although from a different thread) yesterday and this time I got a core dump:

epics> CA client library tcp receive thread terminating due to a C++ exception
FATAL: exception not rethrown
Abort (core dumped)

Unfortunately the backtrace didn't give me any clues where the exception was thrown from, but it was very repeatable. I tried deriving all your exception classes from std::exception, but still only ever hit the last resort exception handler, so I knew it wasn't something you were throwing.

Finally I Googled the above "FATAL:" error message, and found the following posting:

From: Boris Kolpackov <[email protected]>
Newsgroups: comp.programming.threads
Subject: Re: "exception not rethrown" problem
Date: Thu, 15 Jun 2006 08:26:18 +0000 (UTC)

"D'artagnan" <[email protected]> writes:

I'm using Pthreads in a C++ program that uses exceptions. When one
thread is cancelled (cancellation state is deferred) by the main
thread, it throws some mysterious exception which cannot even be caught
by "catch(...)". The program aborts with the following error message:

FATAL: exception not rethrown
Abort

Anybody have ideas how to avoid this problem? Specifically, how to
catch the cancellation exception, or how to ignore it? Thanks a lot.

I am pretty sure you are using NPTL on GNU/Linux. NPTL implements
thread cancellation by throwing an (implementation-defined) exception
that you are not allowed to finalize (i.e., you can catch it but you
have to rethrow). The problem is that you cannot identify this
exception in your C++ program. If all your exceptions are derived from
one base or a set of base exceptions, then you can write something
like this:

extern "C"
void*
thread_func (void*)
{
  try
  {
    ...
  }
  catch (std::exception const&)
  {
    // Handle application exceptions here.
  }
  catch (...)
  {
    // Assuming thread cancellation - must rethrow.
    throw;
  }
}

By adding a 'throw;' statement to the end of the 'catch ( ... )' block in tcpiiu.cpp I can prevent the FATAL message, but I then get an error from epicsThread::epicsThreadCallEntryPoint instead, and I still see the message from

epics> CA client library tcp receive thread terminating due to a C++ exception
epicsThread: Unknown C++ exception in thread "CAC-TCP-recv" at Tue Dec 19 2006 16:56:15.182832000

There's a lot more discussion about this topic on the c++-pthreads mailing list, and in fact a huge thread from last July that starts here talks about how this issue might be solved, although I don't think they came to a final conclusion:
    http://www.codesourcery.com/archives/c++-pthreads/msg00324.html

The upshot of this is that on Linux using NPTL there is currently no way to portably use pthread_cancel() with a C++ program because on NPTL the pthread_cleanup_push/pop mechanism is coded using the C++ exception mechanism. Our posix implementation of osdThread.c registers an atexit() handler which calls pthread_cancel() for each of the threads we have started, thus confirming that we're in exactly the situation that is recognizably broken on Linux.

I have a suggestion for our code: I'd like to introduce a new macro into epicsThread.h (which will be overridden in os/linux/osdThread.h) called something like epicsThreadRethrow (better name welcomed). On linux this will expand to 'throw', and to something like '(void)0' in all other implementations. We then suggest that this be placed in all last-ditch catch clauses after any necessary cleanup operations but before printing warning messages. The result will be to suppress those warning messages on Linux since we expect this exception at thread closedown.

This does mean that we should change all our exception classes to derive from std::exception (or from our own standard exception class preferably based on std::exception) in order to be able to identify them when caught, since we can't rely on the last-ditch handler on Linux. I don't think we should do this for R3.14.9 since it's going to need some development work, but it should be a goal for the next release.

Comments, questions, objections?

There may be another solution on NPTL that avoids rethrowing the exception, but it still requires inserting code into all last-ditch exception handlers to suppress the FATAL: message, as it doesn't prevent the exception from being thrown in the first place. I don't think it's possible to distinguish a cancellation exception, although that would be the best solution if someone can work out how to do that.

- Andrew
--
There is considerable overlap between the intelligence of the smartest
bears and the dumbest tourists -- Yosemite National Park Ranger

References:
RE: C++ Exceptions from CAC-UDP on exit Jeff Hill

Navigate by Date:
Prev: EPICS R3.14.9 experiences Rees, NP (Nick)
Next: Re: EPICS R3.14.9 experiences Andrew Johnson
Index: 2002  2003  2004  2005  <20062007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: RE: C++ Exceptions from CAC-UDP on exit Jeff Hill
Next: Re: C++ Exceptions from CAC-UDP on exit Ernest L. Williams Jr.
Index: 2002  2003  2004  2005  <20062007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 02 Feb 2012 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·