diff mbox

Fix quick_exit to match C++11 specification.

Message ID 57525107.5060500@redhat.com
State New
Headers show

Commit Message

Carlos O'Donell June 4, 2016, 3:54 a.m. UTC
On 06/03/2016 02:25 PM, Florian Weimer wrote:
> On 06/03/2016 06:38 PM, Carlos O'Donell wrote:
>> +ifneq (,$(CXX))
>> +CFLAGS-tst-quick_exit.o = -std=c++11
>> +LDLIBS-tst-quick_exit = -lstdc++
>> +else
>> +tests-unsupported += tst-quick_exit
>> +endif
> 
> I think you need this instead:
> 
> ifneq ($(have-cxx-thread_local),yes)
> tests-unsupported += tst-quick-exit
> endif

I do. Good catch.

> It may make sense to test destruction from a non-main thread, too
> (with a separate test case, one test should not link against
> libpthread).

Added.

v2
- Added tst-thread-quick_exit test to call quick_exit from non-main thread.
- Only run tests if $(have-cxx-thread_local) is yes.
- Version quick_exit, leaving old version that still runs destructors.
  Old code is now potentially ~7 years old and might need this behaviour.
- Use test-skeleton.c for tests.

If nobody objects I'll check this in shortly.

Thank goodnesss for `make update-all-abi` ;-)

Comments

Florian Weimer June 5, 2016, 3:13 p.m. UTC | #1
On 06/04/2016 05:54 AM, Carlos O'Donell wrote:
> +  GLIBC_2.24 {
> +    quick_exit;
> +  }

One more question:

Do we really need a new version?  Is it correct to version quick_exit? 
Would it be more correct to version __cxa_thread_atexit_impl instead 
because whether the destructor runs at thread exit seems more like a 
property of the code that registers the destructor, than the code that 
invokes quick_exit?

Thanks,
Florian
Carlos O'Donell June 7, 2016, 12:22 a.m. UTC | #2
On 06/05/2016 11:13 AM, Florian Weimer wrote:
> On 06/04/2016 05:54 AM, Carlos O'Donell wrote:
> Do we really need a new version?  Is it correct to version
> quick_exit? Would it be more correct to version
> __cxa_thread_atexit_impl instead because whether the destructor runs
> at thread exit seems more like a property of the code that registers
> the destructor, than the code that invokes quick_exit?

I don't quite follow.

It is the call to exit, _Exit/_exit, or quick_exit which decides
the sequence of process termination actions.

Particularly in C++ the quick_exit call must not run destructors
for thread local objects, since the standard mandates that.

Changing __cxa_thread_atexit_impl would be more complicated than
just changing quick_exit.
Florian Weimer June 7, 2016, 6:18 a.m. UTC | #3
On 06/07/2016 02:22 AM, Carlos O'Donell wrote:
> On 06/05/2016 11:13 AM, Florian Weimer wrote:
>> On 06/04/2016 05:54 AM, Carlos O'Donell wrote:
>> Do we really need a new version?  Is it correct to version
>> quick_exit? Would it be more correct to version
>> __cxa_thread_atexit_impl instead because whether the destructor runs
>> at thread exit seems more like a property of the code that registers
>> the destructor, than the code that invokes quick_exit?
>
> I don't quite follow.
>
> It is the call to exit, _Exit/_exit, or quick_exit which decides
> the sequence of process termination actions.

Well yes, in your implementation of the compat symbol.  But it doesn't 
has to be this way, and it may not be the “correct” approach.

> Particularly in C++ the quick_exit call must not run destructors
> for thread local objects, since the standard mandates that.
>
> Changing __cxa_thread_atexit_impl would be more complicated than
> just changing quick_exit.

I put “correct” in scare quotes because I'm not convinced that we'd need 
a compat symbol at all for this (but if we do, it probably should be put 
on the registration, storing a flag along with callback registration data).

Florian
Carlos O'Donell June 7, 2016, 7:50 a.m. UTC | #4
On 06/07/2016 02:18 AM, Florian Weimer wrote:
>> I don't quite follow.
>>
>> It is the call to exit, _Exit/_exit, or quick_exit which decides
>> the sequence of process termination actions.
> 
> Well yes, in your implementation of the compat symbol. But it doesn't
> has to be this way, and it may not be the “correct” approach.
> 
>> Particularly in C++ the quick_exit call must not run destructors
>> for thread local objects, since the standard mandates that.
>>
>> Changing __cxa_thread_atexit_impl would be more complicated than
>> just changing quick_exit.
> 
> I put “correct” in scare quotes because I'm not convinced that we'd
> need a compat symbol at all for this (but if we do, it probably
> should be put on the registration, storing a flag along with callback
> registration data).

What do we gain by this?
Florian Weimer June 7, 2016, 9:27 a.m. UTC | #5
On 06/07/2016 09:50 AM, Carlos O'Donell wrote:

>> I put “correct” in scare quotes because I'm not convinced that we'd
>> need a compat symbol at all for this (but if we do, it probably
>> should be put on the registration, storing a flag along with callback
>> registration data).
>
> What do we gain by this?

I don't think it matters.  I think the compat symbol is overkill.

Florian
Carlos O'Donell June 7, 2016, 9:56 a.m. UTC | #6
On 06/07/2016 05:27 AM, Florian Weimer wrote:
> On 06/07/2016 09:50 AM, Carlos O'Donell wrote:
> 
>>> I put “correct” in scare quotes because I'm not convinced that we'd
>>> need a compat symbol at all for this (but if we do, it probably
>>> should be put on the registration, storing a flag along with callback
>>> registration data).
>>
>> What do we gain by this?
> 
> I don't think it matters.  I think the compat symbol is overkill.

That is a fine opinion to have.

Thanks for being open to explaining your position.
Adhemerval Zanella Netto June 7, 2016, 12:02 p.m. UTC | #7
On 07/06/2016 06:56, Carlos O'Donell wrote:
> On 06/07/2016 05:27 AM, Florian Weimer wrote:
>> On 06/07/2016 09:50 AM, Carlos O'Donell wrote:
>>
>>>> I put “correct” in scare quotes because I'm not convinced that we'd
>>>> need a compat symbol at all for this (but if we do, it probably
>>>> should be put on the registration, storing a flag along with callback
>>>> registration data).
>>>
>>> What do we gain by this?
>>
>> I don't think it matters.  I think the compat symbol is overkill.
> 
> That is a fine opinion to have.
> 
> Thanks for being open to explaining your position.
> 

I also do not see compelling reason to provide a compat symbol this
specific issue.  The destruction handles are registered only with
__cxa_thread_atexit_impl and it is used only for thread_local on
C++.  And C++ definition on quick_exit stated that it does not
run the TLS destructors, so a program that relies on it is just
expecting a non-conforming implementation behaviour.
Carlos O'Donell June 7, 2016, 1:17 p.m. UTC | #8
On 06/07/2016 08:02 AM, Adhemerval Zanella wrote:
> 
> 
> On 07/06/2016 06:56, Carlos O'Donell wrote:
>> On 06/07/2016 05:27 AM, Florian Weimer wrote:
>>> On 06/07/2016 09:50 AM, Carlos O'Donell wrote:
>>>
>>>>> I put “correct” in scare quotes because I'm not convinced that we'd
>>>>> need a compat symbol at all for this (but if we do, it probably
>>>>> should be put on the registration, storing a flag along with callback
>>>>> registration data).
>>>>
>>>> What do we gain by this?
>>>
>>> I don't think it matters.  I think the compat symbol is overkill.
>>
>> That is a fine opinion to have.
>>
>> Thanks for being open to explaining your position.
>>
> 
> I also do not see compelling reason to provide a compat symbol this
> specific issue.  The destruction handles are registered only with
> __cxa_thread_atexit_impl and it is used only for thread_local on
> C++.  And C++ definition on quick_exit stated that it does not
> run the TLS destructors, so a program that relies on it is just
> expecting a non-conforming implementation behaviour. 

The problem is that we've had a quick_exit that runs thread local
destructors since glibc 2.10 (2009), so that means 7 years of applications
having the wrong behaviour, testing with the wrong behaviour, and maybe
even relying on the wrong behaviour to shutdown certain objects in the
event of a quick_exit call.

Therefore to be conservative I versioned the interface for those old
binaries. It feels a bit like overkill, but I also think we've been a bit
cavalier lately and should version more often.
Florian Weimer June 7, 2016, 1:48 p.m. UTC | #9
On 06/07/2016 03:17 PM, Carlos O'Donell wrote:

>> I also do not see compelling reason to provide a compat symbol this
>> specific issue.  The destruction handles are registered only with
>> __cxa_thread_atexit_impl and it is used only for thread_local on
>> C++.  And C++ definition on quick_exit stated that it does not
>> run the TLS destructors, so a program that relies on it is just
>> expecting a non-conforming implementation behaviour.
>
> The problem is that we've had a quick_exit that runs thread local
> destructors since glibc 2.10 (2009),

How so?  You only changed behavior for the 2.18 TLS dtor support added here:

commit ba384f6ed9275f3966505f2375b56d169e3dc588
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Mon Feb 18 19:08:21 2013 +0530

     C++11 thread_local destructors support

I don't see how your change makes a different for the libstdc++ 
approximation.

What am I missing?

Thanks,
Florian
Carlos O'Donell June 8, 2016, 7:19 p.m. UTC | #10
On 06/07/2016 09:48 AM, Florian Weimer wrote:
> On 06/07/2016 03:17 PM, Carlos O'Donell wrote:
> 
>>> I also do not see compelling reason to provide a compat symbol this
>>> specific issue.  The destruction handles are registered only with
>>> __cxa_thread_atexit_impl and it is used only for thread_local on
>>> C++.  And C++ definition on quick_exit stated that it does not
>>> run the TLS destructors, so a program that relies on it is just
>>> expecting a non-conforming implementation behaviour.
>>
>> The problem is that we've had a quick_exit that runs thread local
>> destructors since glibc 2.10 (2009),
> 
> How so?  You only changed behavior for the 2.18 TLS dtor support added here:

You are absolutely right.

In which case it's only 3 years of usage.

> commit ba384f6ed9275f3966505f2375b56d169e3dc588
> Author: Siddhesh Poyarekar <siddhesh@redhat.com>
> Date:   Mon Feb 18 19:08:21 2013 +0530
> 
>     C++11 thread_local destructors support
> 
> I don't see how your change makes a different for the libstdc++ approximation.
> 
> What am I missing?

Nothing.

* Is 3 years enough usage to justify a compat symbol?

* Is the cost of the compat symbol and long term maintenance
  worth the benefit to our users?

My feeling is that this is a "yes" in this particular case, and
I did the work to fix the interface and test the compat symbol.

Are there any other downsides that I missed?
Florian Weimer June 8, 2016, 7:41 p.m. UTC | #11
On 06/08/2016 09:19 PM, Carlos O'Donell wrote:
> On 06/07/2016 09:48 AM, Florian Weimer wrote:
>> On 06/07/2016 03:17 PM, Carlos O'Donell wrote:
>>
>>>> I also do not see compelling reason to provide a compat symbol this
>>>> specific issue.  The destruction handles are registered only with
>>>> __cxa_thread_atexit_impl and it is used only for thread_local on
>>>> C++.  And C++ definition on quick_exit stated that it does not
>>>> run the TLS destructors, so a program that relies on it is just
>>>> expecting a non-conforming implementation behaviour.
>>>
>>> The problem is that we've had a quick_exit that runs thread local
>>> destructors since glibc 2.10 (2009),
>>
>> How so?  You only changed behavior for the 2.18 TLS dtor support added here:
>
> You are absolutely right.
>
> In which case it's only 3 years of usage.

Or non-usage.  I don't think there are many users.  In Fedora rawhide, 
the only reference is in some auto-generated wrapper code in the smokeqt 
package.

>> commit ba384f6ed9275f3966505f2375b56d169e3dc588
>> Author: Siddhesh Poyarekar <siddhesh@redhat.com>
>> Date:   Mon Feb 18 19:08:21 2013 +0530
>>
>>     C++11 thread_local destructors support
>>
>> I don't see how your change makes a different for the libstdc++ approximation.
>>
>> What am I missing?
>
> Nothing.
>
> * Is 3 years enough usage to justify a compat symbol?

As I tried to explain, it's unclear where to put the compat symbol.

> * Is the cost of the compat symbol and long term maintenance
>   worth the benefit to our users?

I doubt it, every additional symbol makes dynamic linking a tiny bit slower.

Florian
Carlos O'Donell June 8, 2016, 8:21 p.m. UTC | #12
On 06/08/2016 03:41 PM, Florian Weimer wrote:
>> In which case it's only 3 years of usage.
> 
> Or non-usage. I don't think there are many users. In Fedora rawhide,
> the only reference is in some auto-generated wrapper code in the
> smokeqt package.

This doesn't count the user applications built on top of Fedora
or other downstream rpm-based distributions though.

The real complication is that we can't know how many users of a public
API, and thus once we release the API we generally support it forever.

There are some cases where we have recently deprecated very very old
headers, or types, but none of these break backwards compatibility with
existing applications.
 
>>> commit ba384f6ed9275f3966505f2375b56d169e3dc588
>>> Author: Siddhesh Poyarekar <siddhesh@redhat.com>
>>> Date:   Mon Feb 18 19:08:21 2013 +0530
>>>
>>>     C++11 thread_local destructors support
>>>
>>> I don't see how your change makes a different for the libstdc++ approximation.
>>>
>>> What am I missing?
>>
>> Nothing.
>>
>> * Is 3 years enough usage to justify a compat symbol?
> 
> As I tried to explain, it's unclear where to put the compat symbol.

In the case of quick_exit, we need only sufficient state such that
the lower-level exit helpers know now to call thread_local destructors.

In the case of __cxa_thread_atexit_impl, the new version would need to
register destructors in another list which is not normally called by
the code path that quick_exit uses, but is called by the path that
exit uses. Given that the code to call those lower-level exit helpers
is all consolidated in one place to reduce duplication, it would be
more complicated versioning __cxa_thread_atexit_impl.

However, it is zero complication if we don't versioning anything.

>> * Is the cost of the compat symbol and long term maintenance
>>   worth the benefit to our users?
> 
> I doubt it, every additional symbol makes dynamic linking a tiny bit slower.

The problem is that a consequence of our failure is the users
application doesn't work. So we should err on the side of caution.

Even if additional symbols make dynamic linking a tiny bit slower,
that's a distinct problem we need to consider solving other ways.

In summary:
- I am being conservative by versioning quick_exit.
- quick_exit is in my opinion the easiest interface to version
  and logically related to the quick_exit conformance issue with
  C++.
- We do need to look at making dynamic linking faster. We might start
  with: bug 15310, bug 17645.
Adhemerval Zanella Netto June 8, 2016, 8:28 p.m. UTC | #13
On 08/06/2016 17:21, Carlos O'Donell wrote:
> On 06/08/2016 03:41 PM, Florian Weimer wrote:
>>> In which case it's only 3 years of usage.
>>
>> Or non-usage. I don't think there are many users. In Fedora rawhide,
>> the only reference is in some auto-generated wrapper code in the
>> smokeqt package.
> 
> This doesn't count the user applications built on top of Fedora
> or other downstream rpm-based distributions though.
> 
> The real complication is that we can't know how many users of a public
> API, and thus once we release the API we generally support it forever.
> 
> There are some cases where we have recently deprecated very very old
> headers, or types, but none of these break backwards compatibility with
> existing applications.
>  
>>>> commit ba384f6ed9275f3966505f2375b56d169e3dc588
>>>> Author: Siddhesh Poyarekar <siddhesh@redhat.com>
>>>> Date:   Mon Feb 18 19:08:21 2013 +0530
>>>>
>>>>     C++11 thread_local destructors support
>>>>
>>>> I don't see how your change makes a different for the libstdc++ approximation.
>>>>
>>>> What am I missing?
>>>
>>> Nothing.
>>>
>>> * Is 3 years enough usage to justify a compat symbol?
>>
>> As I tried to explain, it's unclear where to put the compat symbol.
> 
> In the case of quick_exit, we need only sufficient state such that
> the lower-level exit helpers know now to call thread_local destructors.
> 
> In the case of __cxa_thread_atexit_impl, the new version would need to
> register destructors in another list which is not normally called by
> the code path that quick_exit uses, but is called by the path that
> exit uses. Given that the code to call those lower-level exit helpers
> is all consolidated in one place to reduce duplication, it would be
> more complicated versioning __cxa_thread_atexit_impl.
> 
> However, it is zero complication if we don't versioning anything.
> 
>>> * Is the cost of the compat symbol and long term maintenance
>>>   worth the benefit to our users?
>>
>> I doubt it, every additional symbol makes dynamic linking a tiny bit slower.
> 
> The problem is that a consequence of our failure is the users
> application doesn't work. So we should err on the side of caution.
> 
> Even if additional symbols make dynamic linking a tiny bit slower,
> that's a distinct problem we need to consider solving other ways.
> 
> In summary:
> - I am being conservative by versioning quick_exit.
> - quick_exit is in my opinion the easiest interface to version
>   and logically related to the quick_exit conformance issue with
>   C++.
> - We do need to look at making dynamic linking faster. We might start
>   with: bug 15310, bug 17645.
> 

I personally do not see a compelling reason to provide a compatibility
symbol to standard defined C++11 symbol that explicit states its
interface regarding the offended functionality.  I would see a reason
to add compatibility if the functionality was not defined or if the
interface was not really setted in the time the function was added in
GLIBC.

If the C++11 application is relying on thread_local destruction
for quick_exit, it is a non-conforming one that might only runs correctly
on GLIBC.  I see this as an application issue, not a GLIBC one.
Carlos O'Donell June 8, 2016, 8:54 p.m. UTC | #14
On 06/08/2016 04:28 PM, Adhemerval Zanella wrote:
> If the C++11 application is relying on thread_local destruction
> for quick_exit, it is a non-conforming one that might only runs correctly
> on GLIBC.  I see this as an application issue, not a GLIBC one.
 
I agree in principle, but in practice we need compat symbols. The only
good argument is the one Florian presents which is: data suggests that
there are so few users it doesn't matter.

At some point the flawed implementation becomes the standard.
Adhemerval Zanella Netto June 9, 2016, 2:50 p.m. UTC | #15
On 08/06/2016 17:54, Carlos O'Donell wrote:
> On 06/08/2016 04:28 PM, Adhemerval Zanella wrote:
>> If the C++11 application is relying on thread_local destruction
>> for quick_exit, it is a non-conforming one that might only runs correctly
>> on GLIBC.  I see this as an application issue, not a GLIBC one.
>  
> I agree in principle, but in practice we need compat symbols. The only
> good argument is the one Florian presents which is: data suggests that
> there are so few users it doesn't matter.
> 
> At some point the flawed implementation becomes the standard.
> 

Fair enough.
diff mbox

Patch

diff --git a/stdlib/Makefile b/stdlib/Makefile
index e0eeada..fc6f23d 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -76,8 +76,18 @@  tests		:= tst-strtol tst-strtod testmb testrand testsort testdiv   \
 		   tst-secure-getenv tst-strtod-overflow tst-strtod-round   \
 		   tst-tininess tst-strtod-underflow tst-tls-atexit	    \
 		   tst-setcontext3 tst-tls-atexit-nodelete		    \
-		   tst-strtol-locale tst-strtod-nan-locale tst-strfmon_l
+		   tst-strtol-locale tst-strtod-nan-locale tst-strfmon_l    \
+		   tst-quick_exit tst-thread-quick_exit
 tests-static	:= tst-secure-getenv
+ifeq ($(have-cxx-thread_local),yes)
+CFLAGS-tst-quick_exit.o = -std=c++11
+LDLIBS-tst-quick_exit = -lstdc++
+CFLAGS-tst-thread-quick_exit.o = -std=c++11
+LDLIBS-tst-thread-quick_exit = -lstdc++
+$(objpfx)tst-thread-quick_exit: $(shared-thread-library)
+else
+tests-unsupported += tst-quick_exit tst-thread-quick_exit
+endif
 
 modules-names	= tst-tls-atexit-lib
 extra-test-objs += $(addsuffix .os, $(modules-names))
diff --git a/stdlib/Versions b/stdlib/Versions
index 60b628d..9c06b43 100644
--- a/stdlib/Versions
+++ b/stdlib/Versions
@@ -109,6 +109,9 @@  libc {
   GLIBC_2.18 {
     __cxa_thread_atexit_impl;
   }
+  GLIBC_2.24 {
+    quick_exit;
+  }
   GLIBC_PRIVATE {
     # functions which have an additional interface since they are
     # are cancelable.
diff --git a/stdlib/exit.c b/stdlib/exit.c
index 9d3c5f4..b50b178 100644
--- a/stdlib/exit.c
+++ b/stdlib/exit.c
@@ -31,13 +31,14 @@  DEFINE_HOOK (__libc_atexit, (void))
 void
 attribute_hidden
 __run_exit_handlers (int status, struct exit_function_list **listp,
-		     bool run_list_atexit)
+		     bool run_list_atexit, bool run_dtors)
 {
   /* First, call the TLS destructors.  */
 #ifndef SHARED
   if (&__call_tls_dtors != NULL)
 #endif
-    __call_tls_dtors ();
+    if (run_dtors)
+      __call_tls_dtors ();
 
   /* We do it this way to handle recursive calls to exit () made by
      the functions registered with `atexit' and `on_exit'. We call
@@ -101,6 +102,6 @@  __run_exit_handlers (int status, struct exit_function_list **listp,
 void
 exit (int status)
 {
-  __run_exit_handlers (status, &__exit_funcs, true);
+  __run_exit_handlers (status, &__exit_funcs, true, true);
 }
 libc_hidden_def (exit)
diff --git a/stdlib/exit.h b/stdlib/exit.h
index b28a4c9..6cf8889 100644
--- a/stdlib/exit.h
+++ b/stdlib/exit.h
@@ -64,7 +64,7 @@  extern struct exit_function *__new_exitfn (struct exit_function_list **listp);
 extern uint64_t __new_exitfn_called attribute_hidden;
 
 extern void __run_exit_handlers (int status, struct exit_function_list **listp,
-				 bool run_list_atexit)
+				 bool run_list_atexit, bool run_dtors)
   attribute_hidden __attribute__ ((__noreturn__));
 
 extern int __internal_atexit (void (*func) (void *), void *arg, void *d,
diff --git a/stdlib/quick_exit.c b/stdlib/quick_exit.c
index bb47472..effda6a 100644
--- a/stdlib/quick_exit.c
+++ b/stdlib/quick_exit.c
@@ -19,11 +19,25 @@ 
 #include <stdlib.h>
 #include <unistd.h>
 #include <sysdep.h>
+#include <shlib-compat.h>
 #include "exit.h"
 
+void
+__new_quick_exit (int status)
+{
+  /* The new quick_exit, following C++11 18.5.12, does not run object
+     destructors.  */
+  __run_exit_handlers (status, &__quick_exit_funcs, false, false);
+}
+versioned_symbol (libc, __new_quick_exit, quick_exit, GLIBC_2_24);
 
+#if SHLIB_COMPAT(libc, GLIBC_2_10, GLIBC_2_24)
 void
-quick_exit (int status)
+attribute_compat_text_section
+__old_quick_exit (int status)
 {
-  __run_exit_handlers (status, &__quick_exit_funcs, false);
+  /* The old quick_exit runs thread_local destructors.  */
+  __run_exit_handlers (status, &__quick_exit_funcs, false, true);
 }
+compat_symbol (libc, __old_quick_exit, quick_exit, GLIBC_2_10);
+#endif
diff --git a/stdlib/tst-quick_exit.cc b/stdlib/tst-quick_exit.cc
new file mode 100644
index 0000000..c4a15a9
--- /dev/null
+++ b/stdlib/tst-quick_exit.cc
@@ -0,0 +1,40 @@ 
+/* Bug 20198: Do not call object destructors at exit.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+#include <cstdlib>
+
+struct A
+{
+  ~A() { abort(); }
+};
+
+thread_local A a;
+
+static int
+do_test()
+{
+  (void)a;
+  /* The C++11 standard in 18.5.12 says:
+     "Objects shall not be destroyed as a result of calling
+      quick_exit."
+     If quick_exit calls the destructors the test aborts.  */
+  std::quick_exit(0);
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/stdlib/tst-thread-quick_exit.cc b/stdlib/tst-thread-quick_exit.cc
new file mode 100644
index 0000000..307d2a2
--- /dev/null
+++ b/stdlib/tst-thread-quick_exit.cc
@@ -0,0 +1,50 @@ 
+/* Bug 20198: Do not call object destructors at exit.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+#include <cstdlib>
+#include <thread>
+
+struct A
+{
+  ~A() { abort(); }
+};
+
+thread_local A a1;
+thread_local A a2;
+
+/* Call std::quick_exit from a non-main thread.  */
+void non_main_thread (void)
+{
+  (void)a1;
+  /* The C++11 standard in 18.5.12 says:
+     "Objects shall not be destroyed as a result of calling
+      quick_exit."
+     If quick_exit calls the destructors the test aborts.  */
+  std::quick_exit (0);
+}
+
+static int
+do_test()
+{
+  (void)a2;
+  std::thread th (non_main_thread);
+  th.join ();
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/arm/nacl/libc.abilist b/sysdeps/arm/nacl/libc.abilist
index 0560510..2f7751d 100644
--- a/sysdeps/arm/nacl/libc.abilist
+++ b/sysdeps/arm/nacl/libc.abilist
@@ -1840,3 +1840,4 @@  GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
+GLIBC_2.24 quick_exit F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 7981817..3878891 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2088,6 +2088,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmmsg F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmmsg F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 0c1e1ac..5ce7e10 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -1999,6 +1999,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmmsg F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmmsg F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index 2b2f9f0..9f8eecc 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -89,6 +89,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmsg F
 GLIBC_2.4 GLIBC_2.4 A
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 84e8431..421b6fe 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1853,6 +1853,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmsg F
 GLIBC_2.3 GLIBC_2.3 A
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 0229cd6..b7fc26c 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2011,6 +2011,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmsg F
 GLIBC_2.3 GLIBC_2.3 A
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index b1388d1..e0df2e3 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1875,6 +1875,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmmsg F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmmsg F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 3a498cb..f80cdfe 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -90,6 +90,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmsg F
 GLIBC_2.4 GLIBC_2.4 A
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 948b050..9132c26 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1967,6 +1967,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmsg F
 GLIBC_2.3 GLIBC_2.3 A
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index d7ba0be..9443927 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2088,5 +2088,6 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmsg F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 87bb49b..69386b2 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1942,6 +1942,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmsg F
 GLIBC_2.3 GLIBC_2.3 A
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 1a415ab..62ba3f9 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1940,6 +1940,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmsg F
 GLIBC_2.3 GLIBC_2.3 A
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 949761b..49b2ad7 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1938,6 +1938,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmsg F
 GLIBC_2.3 GLIBC_2.3 A
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 0e2ff75..445db92 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1933,6 +1933,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmmsg F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmmsg F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 75ef1ab..d854b6d 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2129,5 +2129,6 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmsg F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 5a0890e..bcb4bd1 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1971,6 +1971,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmsg F
 GLIBC_2.3 GLIBC_2.3 A
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index adbe736..01f4957 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1976,6 +1976,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmsg F
 GLIBC_2.3 GLIBC_2.3 A
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index 85286c4..8348670 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2176,6 +2176,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmmsg F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmmsg F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index 0abd098..3de5d61 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -90,6 +90,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmmsg F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmmsg F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 03983df..761f340 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1971,6 +1971,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmsg F
 GLIBC_2.3 GLIBC_2.3 A
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 03a9b97..b7f5371 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1872,6 +1872,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmmsg F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmmsg F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index a2d85e6..fb58c06 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1857,6 +1857,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmsg F
 GLIBC_2.3 GLIBC_2.3 A
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index c51e790..01260e2 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1963,6 +1963,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmsg F
 GLIBC_2.3 GLIBC_2.3 A
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 38b976f..8884d4e 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1901,6 +1901,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmmsg F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmmsg F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index cd48be1..81eea08 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2095,5 +2095,6 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmsg F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index 07b1332..9ce9b57 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2095,6 +2095,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmmsg F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmmsg F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index cd48be1..81eea08 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2095,5 +2095,6 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmsg F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index baea1f5..03549b1 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1852,6 +1852,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmmsg F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmmsg F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 4f52e2e..86dab3f 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2095,5 +2095,6 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 quick_exit F
 GLIBC_2.24 recvmsg F
 GLIBC_2.24 sendmsg F