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

Anthony Williams anthony at justsoftwaresolutions.co.uk
Tue Nov 16 08:00:37 GMT 2010


On 15/11/10 16:21, Howard Hinnant wrote:
> On Nov 15, 2010, at 10:55 AM, Anthony Williams wrote:
>
>> I appreciate that if the data is not present in code compiled to
>> the C++03 ABI then C++0x code can only depend on C++0x code.
>> However, can't the ABI be made backwards compatible, so it remains
>> compatible with the C++03 ABI **and** is compatible with the new
>> C++0x ABI? This would avoid "doubling the size of the OS". Of
>> course, it depends on the details.
>
> To make this change, I would need to see an implemented
> backwards-compatible Itanium ABI which successfully passed through
> review at cxx-abi-dev at codesourcery.com.  I have not personally come
> up with a design which I thought would be implementable and pass such
> a review.

In order to clone exceptions you need two things: the size of the object 
to clone (so you can allocate space for the new one), and the ability to 
call the copy constructor so you can actually do the copy.

I've looked at the Itanium ABI at 
http://www.codesourcery.com/public/cxx-abi/abi.html to try and see where 
this could be done.

One option I see would be to add a new class derived from 
abi::__class_type_info that had virtual member functions for the size 
and copy constructor:

class __copyable_class_type_info: public __class_type_info
{
public:
     size_t __object_size;
     virtual void __copy_construct(void* __source, void* __dest)=0;
};

You would need similar derived classes for __si_class_type_info and 
__vmi_class_type_info.

Because these are derived classes, they shouldn't affect the existing 
ABI structures. The size of non-class types can be determined from the 
type directly, since all pointers have the same size and fundamental 
types have a fixed size under the ABI. Such types can also be copied 
with memcpy().

rethrow_exception can then check the type_info pointed to by the 
exceptionType member of the __cxa_exception header, and either

(i) copy the exception with memcpy (because it's a fundamental type or 
pointer)

(ii) throw bad_alloc because this is an old ABI exception and cannot 
therefore be copied

(iii) dynamic_cast the type info to __copyable_class_type_info use the 
new __object_size and __copy_construct virtual functions to clone the 
exception

A second object is to add the size and copy construction functions to 
the __cxa_exception header. The ABI says "By convention, a 
__cxa_exception pointer points at the C++ object representing the 
exception being thrown, immediately following the header. The header 
structure is accessed at a negative offset from the __cxa_exception 
pointer. This layout allows consistent treatment of exception objects 
from different languages (or different implementations of the same 
language), and allows future extensions of the header structure while 
maintaining binary compatibility. "

We could therefore take advantage of this leeway to "extend the header 
structure while maintaining binary compatibility" to add the new size 
and copy construction members.

What do you think?

>> Is there nothing else in C++0x that breaks the ABI? There are
>> certainly a lot of language facilities that are not in C++03. Is
>> Apple going to oppose any change that breaks the ABI?
>
> Apple currently has a migration strategy:  For all "high level" parts
> of C++0x, we will version the ABI using inline namespaces.  This
> allows for separate C++03 and C++0x ABI's to be shipped on the same
> OS and the only doubling is in the OS-supplied dyld of the std::lib
> (we will ship C++03 and C++0x std::libs). Applications and dyld's can
> migrate or not.  If two dyld's using the different ABI's are used in
> the same application, they will either work (because they share the
> same ABI, or they do not expose ABI-versioned std::lib components in
> their interface), or they will fail at link time.  std::string is an
> obvious example that will be ABI-incompatible (ABI-versioned) between
> C++03 and C++0x.
>
> However "low level" parts of the std::lib are not versioned, and will
> be ABI compatible across C++03 and C++0x.  These low level parts
> include operator new/delete, so that memory allocated from the C++03
> std::lib can be deallocated by the C++0x lib, and vice-versa.  And
> exception throwing/catching is also ABI compatible across the C++03
> and C++0x.  This is done so that an application can link to dyld1 and
> dyld2, and not have to care which std::lib its dyld's are using.  As
> exceptions bubble up from the dyld's, the application does not need
> to concern itself if these are C++03 or C++0x exceptions.  Even the
> std-defined exception classes are ABI compatible across C++03 and
> C++0x.

Thank you for the info; that makes sense.

Anthony
-- 
Author of C++ Concurrency in Action     http://www.stdthread.co.uk/book/
just::thread C++0x thread library             http://www.stdthread.co.uk
Just Software Solutions Ltd       http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976



More information about the cpp-threads mailing list