This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix quick_exit to match C++11 specification.


In C++11 18.5.12 says "Objects shall not be destroyed as a 
result of calling quick_exit." In C11 quick_exit is silent
about thread object destruction. Therefore to make glibc
C++ compliant we do not call any thread local destructors.
A new regression test verifies the fix.

I will note that C++11 18.5.3 makes it clear that C++
defines additional requirements for _Exit() to prevent it
from executing destructors.

Given that the point of _Exit() is to terminate the process
immediately it makes sense the C and C++ should line up
and avoid calling destructors.

No failures. New regtest passes.

OK?

-- 
Cheers,
Carlos.

2016-06-03  Carlos O'Donell  <carlos@redhat.com>

	* stdlib/Makefile (tests): Add tst-quick_exit.
	[ifneq (,$CXX)] (CFLAGS-tst-quick_exit.o): Use -stdc=c++11.
	[ifneq (,$CXX)] (LDLIBS-tst-quick_exit): Use -lstdc++ for C++
	program.
	[ifeq (,$CXX)] (tests-unsupported): Add tst-quick_exit.
	* stdlib/exit.c (__run_exit_handlers): Add run_dtors argument.
	If run_dtors is true call __call_tls_dtors.
	(exit): Call __run_exit_handlers with run_dtors set to true.
	* stdlib/exit.h: Add run_dtors argument to __run_exit_handlers
	definition.
	* stdlib/quick_exit.c (quick_exit): Call __run_exit_handlers
	with run_dtors set to false.
	* stdlib/tst-quick_exit.cc: New file.

diff --git a/stdlib/Makefile b/stdlib/Makefile
index e0eeada..d8effc0 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -76,8 +76,15 @@ 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
 tests-static	:= tst-secure-getenv
+ifneq (,$(CXX))
+CFLAGS-tst-quick_exit.o = -std=c++11
+LDLIBS-tst-quick_exit = -lstdc++
+else
+tests-unsupported += tst-quick_exit
+endif
 
 modules-names	= tst-tls-atexit-lib
 extra-test-objs += $(addsuffix .os, $(modules-names))
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..32f8078 100644
--- a/stdlib/quick_exit.c
+++ b/stdlib/quick_exit.c
@@ -25,5 +25,5 @@
 void
 quick_exit (int status)
 {
-  __run_exit_handlers (status, &__quick_exit_funcs, false);
+  __run_exit_handlers (status, &__quick_exit_funcs, false, false);
 }
diff --git a/stdlib/tst-quick_exit.cc b/stdlib/tst-quick_exit.cc
new file mode 100644
index 0000000..d431ec3
--- /dev/null
+++ b/stdlib/tst-quick_exit.cc
@@ -0,0 +1,38 @@
+/* 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;
+
+int
+main()
+{
+  (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;
+}
+


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]