Boost logo

Boost :

From: Alexander Terekhov (TEREKHOV_at_[hidden])
Date: 2002-08-15 12:03:42


Darryl Green wrote:
[...]
> > "On Digital UNIX, an unhandled exception in a thread will ...
>
> On ecos, rtems, amx, psos... there is only 1 "process" - please allow for
at
> least some small chance of success in doing a civilised shutdown over
having
> no chance of doing this.

-------- Original Message --------
Message-ID: <3D5A49FB.CED1038C_at_[hidden]>
Date: Wed, 14 Aug 2002 14:15:55 +0200
From: Alexander Terekhov <terekhov_at_[hidden]>
Newsgroups: comp.programming.threads
Subject: Re: High level thread design question

Alexander Terekhov wrote:
[...]
> -------- Original Message --------
> Alexander Terekhov
> 08/13/2002 04:46 PM
>
> To: boost_at_[hidden]
> cc: pdimov_at_[hidden]
> Subject: Re: Attempting resolution of Threads & Exceptions Issue
>
> Peter Dimov wrote:
> [...]
> > This is a valid concern, but it's possible to have the cake and eat it,
> too.
> > Provide the "unsafe" interface, where thread<R> propagates, as an
> > experiment. Wait for user feedback. Obtain real data on whether the
> mistakes
> > caused by this behavior are a significant problem, and not a small part
> of
> > the vast majority of thread-related errors. Nobody argues with real
data.
> > :-)
>
> If you really want/need it, why don't you simply "wrap" a function
> throwing something useful [that you'd EXPECT and are really going to
> HANDLE in the joined thread(s)] using some return-value/exception(s)-
> variant-holder-functor that would propagate EXPECTED exceptions caught
> and in it's launching/landing-"pad" function-wrapper ON RETURN VALUE
> EXTRACTOR "method" invocation [or f.ex.pthread->join()->
> throwCaughtExceptionIfAny() for void operations, thread cancellation
> aside in this case]? ....

Eric D Crahen wrote:
>
> Hillel Y. Sims wrote:
>
> > I just thought of another one:
> > 4. The standard library already throws exceptions inherited from
> > std::exception, and you don't want to introduce another completely
> > orthogonal hierarchy just for the sake of being contrary.
>
[...]
> ImageFutue f("somefile"); // Start loading an image in another thread
  ^^^^^^^^^^^^^^^^^^^^^^^(A)

> using
> // Image.read()
>
> // .. // Do some other things for a while, setup the
> // frame to display it, find the matching
> // thumbnail that won't take as long to
> // load image, whatever
>
> try {
^^^^^^^(B)

>
> Image& img = f.getImage(); // Get the ImageFuture threads result.
                 ^^^^^^^^^^^(C)

>
> // paint it, print it, etc
>
> } catch(ErrorCorruptImage&) { // not derived from std::exception
> // ... Handle one error one way
> } catch(ErrorFileOpen&) { // not derived from std::exception
> // ... Handle the other error another
> }
[...]
> I don't think having the threads exception unwind another stack is that
> big of a problem for something like this.

The problem is that another thread has its own stack and dynamic context
for exception handling. The EXPECTED handlers are known at the point (B)
in the joiner thread; NOT at the point (A) -- when you start another
thread or just queue a workitem. Now, presuming that future C++ would
provide a mechanism to "extract" a properly ordered typelist of exception
types from exceptions specifications [opened ex.specs. aside -- you'd have
to provide your own typelist or simply catch-wrapper-function], you could
then easily write generic/meta code that would catch all exceptions and
simply store the copy constructed/placed into some >>discriminated union<<
(problems w.r.t. alignments aside) inside that "future-"/"thread-" object,
and later, could then re-throw it on "result extractor method" invocation;
(C) in your example. You could then even provide some optional
unhandledException() hook/handler that would be invoked on "future-"/
thread-" object destruction with never-re-thrown exceptions; it would
then cover "never-joined"/detached "threads"/"futures" case as well.

But that has really NOTHING to do with thread v. process termination
and unwinding/propagation of ALL exceptions, however.

regards,
alexander.

-----------------

David Abrahams wrote:
[...]
> If all the code is exception-neutral and gives the basic guarantee,
> by the time the thread exits, all program invariants are intact.

Even if some throw() operation would suddenly throw? Well, if life is
so perfect as Abrahams seems to paint it, and C++ programs, threads aside,
are meant to recover whatever-is-thrown at any point, then why does the
standard have that nice terminate()->abort() mechanism with UNBELIEVABLY
SHORT list of "situations"/"such cases"... saying *specifically* the
following [emphasized part], to begin with:

"[except.terminate] The terminate() function
 In the following situations exception handling must be abandoned
 for less subtle error handling techniques: ....
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^(*)

 In such cases,

 void terminate();

 is called (18.6.3). In the situation where no matching handler is
 found, it is implementation-defined whether or not the stack is
 unwound before terminate() is called. In all other situations,
 the stack shall not be unwound before terminate() is called."
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

<?!>

regards,
alexander.

(*) < C++ Standard Core Language Active Issues, Revision 22 >

"Bjarne Stroustrup: I strongly prefer to have the call to
 std::terminate() be conforming. I see std::terminate() as
 a proper way to blow away "the current mess" and get to the
 next level of error handling. I do not want that escape to
 be non-conforming - that would imply that programs relying
 on a error handling based on serious errors being handled
 by terminating a process (which happens to be a C++ program)
 in std::terminate() becomes non-conforming. In many systems,
 there are - and/or should be - error-handling and recovery
 mechanisms beyond what is offered by a single C++ program."


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk