[PATCH] pthread_once hangs when init routine throws an exception [BZ #18435]
Jakub Jelinek
jakub@redhat.com
Tue Mar 2 16:43:25 GMT 2021
On Wed, Jul 08, 2015 at 12:09:49PM -0400, Carlos O'Donell wrote:
> > (My understanding: gcc must be very strict about how it marks
> > the code range for exception handling and assume any instruction
> > may throw if it wants -fexceptions -fasynchronous-unwind-tables to
> > work from signal handlers. Current compilers do not seem to support
> > this so glibc internal code should not rely on it, which means the
> > cancellation mechanism should not rely on exception handling at
> > least not when the exception is thrown from the cancel signal
> > handler. I think the gnu toolchain should not try to make pthread
> > cancellation to interoperate with C++ exceptions nor to make
> > exceptions work from signal handlers: no standard requires this
> > behaviour and seems to cause problems).
>
> No, we just need to revert this patch and have C++ implement
> std::call_once by itself.
As has been found, it is unfortunately impossible for C++ to implement it by
itself without breaking ABI.
What libstdc++ needs is either that a modified version of Martin's patch
is committed again, or a new entry-point which is ABI compatible with
pthread_once but ensures the exception behavior is added (or both,
make pthread_once work with exceptions and add an alias to pthread_once
that guarantees that behavior).
The only bug I see in Martin's patch is that he has removed the overrides
altogether.
sysdeps/generic/nptl/pthread.h
defines 3 different implementations of pthread_cleanup_{push,pop}:
1) C++ -fexceptions (using dtor)
2) C -fexceptions (using cleanup attribute)
3) -fno-exceptions one
The override in pthreadP.h which is used only if IS_IN_libpthread is
meant as a better replacement for 3), but isn't a good replacement for 2).
The overrides in pthreadP.h are only used by pthread_once.c, sem_*wait.c and
pthread_join_common.c.
Seems currently everything but pthread_join_common.c is compiled with
-fexceptions -fasynchronous-unwind-tables, so guarding the pthreadP.h
2 #defines (but probably not the function declarations) with
#if !defined(__GNU__) || !defined(__EXCEPTIONS)
seems the way to go to me.
And, perhaps incrementally consider compiling pthread_join_common.c
with -fexceptions -fasynchronous-unwind-tables too.
The pthread_once.c stuff is most important, sure, but if my fuzzy memory
serves me a little, I think for pthread_cancel once it hits a first
non-dtor/cleanup registered cleanup it will just handle the
3) method registered ones and not others, while if it uses the 1)/2)
cleanups, it will continue doing that until it reaches some 3) registered
ones if any.
Jakub
More information about the Libc-alpha
mailing list