[cpp-threads] Issue 1369 --- thread safety of std::rethrow_exception

Boehm, Hans hans.boehm at hp.com
Mon Nov 15 20:31:27 GMT 2010


I still think the issues raised by Nick are really different.

If the exception requires local cleanup (e.g. the GPU state), it should clearly be caught locally, and the cleanup should be performed locally, and then another exception should be rethrown to pass it across threads.  C++0x lets you do that, e.g. by catching the exception inside the async function.  And I don't know how to do better.

Similarly, I think it's a separate issue whether threads should be able to access memory and possibly other resources held by another thread.  Java quite reasonably answers "no" for memory.  This works at the expense of a significant amount of additional heap allocation.  On the other hand, I think that the C and C++ threads model doesn't really work unless you allow cross-thread accesses to thread stacks.  Otherwise I can't invoke a function like an in-place parallel sort on a stack-allocated array.  Every function API would have to document whether it may access its arguments from a different thread, and thus won't work on stack-allocated arguments.

Although debugging cross-thread memory smashes is a serious pain, I think the alternative renders the language largely unusable for general concurrent programming.  It's not hard to find instances of perfectly reasonable cross-thread memory modification in existing C and C++ code, for precisely this reason.

Currently the C++0x draft requires this sort of cross-thread memory access to work, while the C1x draft does not.  This makes some sense, since C caters to more special purpose embedded applications that may have odd requirements, and may be able to live without parallel algorithms that work on stack-allocated data.  But I would be surprised if there were server or workstation C1x implementations that really prohibited cross-thread memory access.

Hans

> -----Original Message-----
> From: cpp-threads-bounces at decadent.org.uk [mailto:cpp-threads-
> bounces at decadent.org.uk] On Behalf Of N.M. Maclaren
> Sent: Saturday, November 13, 2010 3:56 AM
> To: C++ threads standardisation
> Subject: Re: [cpp-threads] Issue 1369 --- thread safety of
> std::rethrow_exception
> 
> On Nov 13 2010, Boehm, Hans wrote:
> >
> >
> > I'm a bit concerned that we're talking about a bunch of different
> things
> > here.  I think the most worrisome scenario for this issue is a
> program
> > that invokes a function with async() and then turns the result into a
> > shared_future, and makes the result f available to multiple threads.
> If
> > the asynchronously run function throws an exception, then that
> exception
> > e may be thrown in several different threads calling f.get().  If one
> of
> > those threads modifies e, we have a data race.
> 
> You get more than one form of data race, actually.  In addition to the
> form that you have been dealing with, you can also get the logical data
> race caused by the conflicting use of a non-shareable resource.  GPUs
> and other attached processors are a good example of that.
> 
> > (The issue of whether you want to pass exceptions between threads is
> > different. C++ certainly doesn't prevent you from handling exceptions
> > locally, but I agree with Anthony that that's not always the right
> > thing.)
> 
> Do you REALLY want to open the wormcan of one thread asychronously
> changing the behaviour of another?  POSIX originally specified that,
> until certain vendors gibbered (I had a bit player part in that), so
> the
> insanity is at least optional.
> 
> Note that I am not saying that the initial handler should not reraise
> ANOTHER exception created from the first one on another thread.
> 
> Taking a look at 18.8.5 Exception Propagation [propagation] indicates
> that a thread A cannot handle an exception raised in thread B unless
> SOME handler for thread B was called to create an exception_ptr object,
> that is precisely what C++ specifies.
> 
> I haven't looked into this area, as I thought it was forbidden, but
> a quick glance shows significant problems with the existing wording.
> 
>     5.2 Constructors and destructors [except.ctor]
>     As control passes from a throw-expression to a handler, destructors
>     are invoked for all automatic objects constructed since the try
>     block was entered. The automatic objects are destroyed in the
>     reverse order of the completion of their construction.
> 
> Now, that's not a problem under two circumstances:
> 
>     1) Destructors are purely scope-based (like try-catch), but C++
> isn't like that.
> 
>     2) Destructors are always 'passive' and never invoke anything
> with cross-thread implications.  I haven't seen any such constraint.
> 
> Without any constraints, you get delights like an exception raised
> by a thread A being handled in thread B after thread A has been killed,
> by which time thread C has got control of the resource that needs
> cleaning up.  With some thought, I could probably think of nastier
> gotchas.
> 
> It's an EVIL problem.  Been there - done that :-(
> 
> Regards,
> Nick Maclaren.
> 
> 
> 
> --
> cpp-threads mailing list
> cpp-threads at decadent.org.uk
> http://www.decadent.org.uk/cgi-bin/mailman/listinfo/cpp-threads



More information about the cpp-threads mailing list