Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

"exception not rethrown" problem

2,122 views
Skip to first unread message

D'artagnan

unread,
Jun 14, 2006, 3:12:30 PM6/14/06
to
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.

Dave Butenhof

unread,
Jun 14, 2006, 6:55:30 PM6/14/06
to
D'artagnan wrote:
> 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

POSIX is a C language standard, and POSIX threads are part of POSIX. For
portable correctness, you need 'extern "C"' linkage for thread start
routines, cancellation cleanup handlers, UNIX signal handlers, and any
other functions in your application called by POSIX. (Anywhere you pass
the address of a function.)

POSIX and C don't know about exceptions.

POSIX cancellation was designed as a "non-C++" mask for exceptions. On
any system that supports exceptions (and any system that supports C++
does support exceptions) we intended that cancellation be implemented
using exceptions. We "advised" (though the POSIX allowance for such
advice is pretty weak) that a "language binding" for any language with
exceptions should implement cancellation on top of them. That was
directed particularly at C++ and Ada.

And there definitely are implementations that work that way.
Unfortunately other vendors just couldn't be bothered to do it sensibly;
or perhaps (generously) just never even thought of it. On systems where
there's a common system-wide exception mechanism built in, it's pretty
natural for all exception-based libraries and languages to use
compatible exceptions -- although defining how they interact can be a
mess. (E.g., as what C++ class would an Ada exception appear; or how
would Ada catch and interpret a thrown C++ string?) Still, it can be
resolved.

OK, it may be obvious you've hit one of my main "hot buttons". Every
UNIX system does exceptions, and there are many languages; and it's just
stupid that they don't interoperate. It'd be even better if there was a
universal architecture that would let them interoperate cleanly; but at
the very least a C++ catch(...) or Ada 'finally' should be able to
finalize any exception thrown by any facility; C++ destructors and POSIX
cleanup handlers should fire when any exception unwinds the controlling
frame. (Unfortunately, beyond that the discussions tend to get mired in
very complicated and often subtle differences of opinion. :-( )

There was once a major effort to define a standard ABI for the Single
UNIX Specification for Itanium-based UNIX family systems. That was when
there were actually multiple vendors (as well as Linux) all planning to
use Itanium. I argued this point until I convinced everyone that the ABI
needed a universal exception infrastructure and had to require that
POSIX cancellation be built on it. One of the vendors involved proposed
a reasonably well generalized version of their C++ library's internal
exception API on which the standard ABI would be built. But as vendors
peeled off in droves, the value of and motivation for a common ABI
became rather tenuous... and then died. While several of the parties
privately committed to implement that ABI anyway, on whatever platforms
they were using, so far as I know nobody actually did.

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

That depends on your OS and compiler. But if catch(...) doesn't work it
may very well not be possible at all.

Ultimately, if you want portability, don't mix pthreads and C++ at all.
In particular, though, avoid cancellation and C++ exceptions in any
program where you do mix them. It'll work smoothly on a very few
platforms, inconsistently and awkwardly on a few others, and not at all
on most.

dav...@webmaster.com

unread,
Jun 15, 2006, 12:26:42 AM6/15/06
to

D'artagnan wrote:

You cannot use cancellation unless all the code that a thread might be
running when it is cancelled knows how to handle being cancelled and
sets appropriate modes and handlers. In all probability, your C++
standard library does not know how to handle being cancelled, so you
must not ever cancel a thread that is or might be running C++ standard
library code (unless you know that your C++ standard library is
cancellation safe).

DS

Boris Kolpackov

unread,
Jun 15, 2006, 4:26:18 AM6/15/06
to
"D'artagnan" <muske...@gmail.com> writes:


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;
}
}

I also created a patch[1] for NPTL that throws a specific C++ exception
(defined in pthread.h) that you can catch (but still have to rethrow):

#include <pthread.h> // std::thread_canceled

try
{
...
}
catch (std::thread_canceled const&)
{
// ...
throw;
}


[1] http://kolpackov.net/projects/glibc/cxx-unwind/


hth,
-boris

D'artagnan

unread,
Jun 15, 2006, 2:13:56 PM6/15/06
to
Many thanks to all answers above. I do learn a lot from you.

I am using NPTL on Linux. All I wanted to do was to have 2 threads. One
of them is an infinite loop (there're cancellation points inside the
loop). At the end of execution it would be cancelled and joined by the
other thread. The two threads were encapsulated in some C++ class. They
were created inside the constructor. The cancellation and joining took
place inside the destructor.

Even if I can catch the cancellation exception (using Boris' scheme), I
still have to rethrow it somehow. But throwing an exception in a
destructor isn't a good idea, so catching the exception really doesn't
help. Is it possible to catch the exception and swallow it? Why must it
be rethrown?

Anyway, probably the best solution is to totally avoid this exception
by not cancelling thread in a C++ program that handles exceptions, just
like what Dave has suggested.

Best regards,
D

0 new messages