In file ./libstdc++-v3/libsupc++/exception (also in trunk) bits/exception_ptr.h is included conditionally: #if (__cplusplus >= 201103L) && (ATOMIC_INT_LOCK_FREE > 1) #include <bits/exception_ptr.h> #include <bits/nested_exception.h> #endif On ARM architecture ATOMIC_INT_LOCK_FREE is set to 1. That leads to losing some functionality of standard library for no good reason.
Was included conditionally before r181869 too, but the condition was different, checked _GLIBCXX_ATOMIC_BUILTINS_4 instead of ATOMIC_INT_LOCK_FREE > 1.
So why is this a regression? Does ARM define _GLIBCXX_ATOMIC_BUILTINS_4 but ATOMIC_INT_LOCK_FREE=1 ? That seems like a bug in those definitions.
This is a regression, because a more specific _GLIBCXX_ATOMIC_BUILTINS_4 was defined (but is no longer available) and now there is defined ATOMIC_INT_LOCK_FREE=1 (I think think the definition is correct, because there were available _GLIBCXX_ATOMIC_BUILTINS_{1,2,4} and no _GLIBCXX_ATOMIC_BUILTINS_8). The other thing is, std::exception_ptr availability should not depend on the fact whether the platform has lock-free atomics or not.
(In reply to Rafał Rawicki from comment #3) > This is a regression, because a more specific _GLIBCXX_ATOMIC_BUILTINS_4 was > defined (but is no longer available) and now there is defined > ATOMIC_INT_LOCK_FREE=1 (I think think the definition is correct, because > there were available _GLIBCXX_ATOMIC_BUILTINS_{1,2,4} and no > _GLIBCXX_ATOMIC_BUILTINS_8). > > The other thing is, std::exception_ptr availability should not depend on the > fact whether the platform has lock-free atomics or not. s/_GLIBCXX_ATOMIC_BUILTINS_4 was defined/_GLIBCXX_ATOMIC_BUILTINS_4 was used/
This is the relevant thread: http://gcc.gnu.org/ml/libstdc++/2011-11/msg00192.html Let's add Andrew in CC.
(In reply to Rafał Rawicki from comment #3) > This is a regression, because a more specific _GLIBCXX_ATOMIC_BUILTINS_4 was > defined (but is no longer available) and now there is defined > ATOMIC_INT_LOCK_FREE=1 (I think think the definition is correct, because > there were available _GLIBCXX_ATOMIC_BUILTINS_{1,2,4} and no > _GLIBCXX_ATOMIC_BUILTINS_8). But ATOMIC_INT_LOCK_FREE only refers to int, i.e. 4-byte integer, so if _GLIBCXX_ATOMIC_BUILTINS_4 was defined then I would expect atomic ops on int to always be lock-free, i.e. the macro should be defined to 2. It's independent of whether atomic ops for 8-byte types are supported. > The other thing is, std::exception_ptr availability should not depend on the > fact whether the platform has lock-free atomics or not. Without them you either need libatomic.so or you risk undefined behaviour such as leaking exception objects or worse, dangling references to destroyed exceptions.
(In reply to Jonathan Wakely from comment #6) > (In reply to Rafał Rawicki from comment #3) > > This is a regression, because a more specific _GLIBCXX_ATOMIC_BUILTINS_4 was > > defined (but is no longer available) and now there is defined > > ATOMIC_INT_LOCK_FREE=1 (I think think the definition is correct, because > > there were available _GLIBCXX_ATOMIC_BUILTINS_{1,2,4} and no > > _GLIBCXX_ATOMIC_BUILTINS_8). > > But ATOMIC_INT_LOCK_FREE only refers to int, i.e. 4-byte integer, so if > _GLIBCXX_ATOMIC_BUILTINS_4 was defined then I would expect atomic ops on int > to always be lock-free, i.e. the macro should be defined to 2. It's > independent of whether atomic ops for 8-byte types are supported. yes. if an integer_type_node is 4 bytes, and the architecture has a 4 byte compare and swap, it should be set to 2 regardless of the lack of an 8 byte lock free operation. this assert should never fail: if (__atomic_always_lock_free(4, NULL) && (sizeof(int) == 4)) assert (ATOMIC_INT_LOCK_FREE == 2); In theory _GLIBCXX_ATOMIC_BUILTINS_4 should have been the same as ATOMIC_INT_LOCK_FREE as long as sizeof (int) == 4 > > > The other thing is, std::exception_ptr availability should not depend on the > > fact whether the platform has lock-free atomics or not. > > Without them you either need libatomic.so or you risk undefined behaviour > such as leaking exception objects or worse, dangling references to > destroyed exceptions.
Closing then.
I'm sorry about my confusion of ATOMIC_INT_LOCK_FREE and _GLIBCXX_ATOMIC_BUILTINS meaning. In the meantime I've checked, when ATOMIC_INT_LOCK_FREE is defined as 2 and the target platform I have problems with (XScale, that is ARMv5), shouldn't have that defined. I'm still checking why I had _GLIBCXX_ATOMIC_BUILTINS_4 on gcc 4.6. I would like to have the same codebase on all platforms and I wouldn't like to stop using std::exception_ptr. Jonathan Wakely wrote, that without hardware support I need libatomic.so or I'd have an undefined behaviour. I do link with libatomic.so - does that mean, I can patch this conditional out (and similar conditional in the exception_ptr.h) and use exception_ptrs? Why it was decided to remove a part of standard library instead of enforcing user to link with libatomic.so?
(In reply to Rafał Rawicki from comment #9) > I do link with libatomic.so - does that mean, I can patch this conditional > out (and similar conditional in the exception_ptr.h) and use exception_ptrs? You could try it. I don't know if it will work correctly. > Why it was decided to remove a part of standard library instead of enforcing > user to link with libatomic.so? That's the usual policy for the library, we don't define components that rely on features that are missing from target platforms.
I'd like to say it should be a bug, if I did not get it wrong. Even for a freestanding implementation, ISO C++11 explicitly specified <exception> as one of required header in table 16, and it should meet the same requirements as for a hosted implementation. Missing exception propagation is definitely not conforming, whether it can actually be implemented or not. Moreover, the standard doesn't specify anything about atomic operations on exception propagation, though it does requires that there should be no data race during some operations. Atomic operations here seem to be purely implementation details. Can it be implemented with something like __shared_ptr's lock policy? This issue also has effect on nested exceptions. Anyway, I feel something indeed wrong when I have to miss std::nested_exception for this reason on a platform which has even no multithreading support at all (as allowed by C++11). Sigh. BTW, libstdc++ manual Table 1.2 just tell me 'Y' for 18.8.5 and 18.8.6. Found no other notes about this issue. So at least it can be a defect of documentation.
Someone just needs to do the work to support it on other targets. One option would be to require libatomic, another would be to not use atomics at all if e.g. !defined(__GTHREADS)
How would one fix this on ARMv7-A for instance? Compiling with "-march=armv7-a" on arm-linux-gnueabihf results in a link error for exception_ptr/current_exception/rethrow_exception etc. gcc_5.3_ARM32HF/bin/gcc -dM - -E -march=armv7-a < /dev/null | grep ATOMIC_INT_LOCK_FREE #define __GCC_ATOMIC_INT_LOCK_FREE 2
(In reply to Philip Deegan from comment #13) > How would one fix this on ARMv7-A for instance? > > Compiling with "-march=armv7-a" on arm-linux-gnueabihf results in a link > error for exception_ptr/current_exception/rethrow_exception etc. > > gcc_5.3_ARM32HF/bin/gcc -dM - -E -march=armv7-a < /dev/null | grep > ATOMIC_INT_LOCK_FREE > #define __GCC_ATOMIC_INT_LOCK_FREE 2 Did you try linking with -latomic ?
Hi, thanks for the quick reply. Yeah I tried with atomic, not much different shared or static, is something special required when building gcc/libc? Linking with --verbose results in: -lmy_lib -latomic -lstdc++ -lm -lgcc_s -lgcc -lpthread -lc -lgcc_s -lgcc /opt/gcc_5.3_ARM32HF/lib/gcc/arm-linux-gnueabihf/5.3.0/crtend.o I'm happy to open another ticket/take this somewhere else.
It should work if you build GCC for ARMv7, i.e. configure --with-arch=armv7-a, but that changes the instruction set used for all the target libraries.
Building bin-utils/gcc/glibc with --with-arch=armv7-a did the trick. Atomic is not required. However, if a thread calls std::current_exception it segfaults in libstdc++-v3/libsupc++/eh_ptr.cc line 190: __cxa_exception *header = globals->caughtExceptions; Can only test static pthread linking currently with Wl,--whole-archive -lpthread -Wl,--no-whole-archive
(In reply to Philip Deegan from comment #17) > However, if a thread calls std::current_exception it segfaults in > libstdc++-v3/libsupc++/eh_ptr.cc line 190: > __cxa_exception *header = globals->caughtExceptions; > > Can only test static pthread linking currently with Wl,--whole-archive > -lpthread -Wl,--no-whole-archive Please file a new bug for that, thanks.
A prototype implementation that doesn't rely on atomics: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg01526.html https://gcc.gnu.org/ml/gcc-patches/2016-09/msg01546.html (both patches are needed).
Fixed by the changes for PR 64735 *** This bug has been marked as a duplicate of bug 64735 ***