nptl: Add PTHREAD_MIN_STACK C++ throw test [BZ #22636]

Message ID 20180112092223.AB07C41610759@oldenburg.str.redhat.com
State New
Headers show
Series
  • nptl: Add PTHREAD_MIN_STACK C++ throw test [BZ #22636]
Related show

Commit Message

Florian Weimer Jan. 12, 2018, 9:22 a.m.
2018-01-12  Florian Weimer  <fweimer@redhat.com>

	[BZ #22636]
	* nptl/tst-minstack-throw.cc: New file.
	* nptl/Makefile (tests): Add tst-minstack-throw.
	(LDLIBS-tst-minstack-throw): Link with libstdc++.
	[!CXX] (tests-unsupported): Add tst-minstack-throw.

Comments

Florian Weimer Jan. 15, 2018, 1:46 p.m. | #1
On 01/12/2018 10:22 AM, Florian Weimer wrote:
> +/* Test that throwing C++ exceptions works with the minimum stack size.

Any comments on this new test?

<https://sourceware.org/ml/libc-alpha/2018-01/msg00438.html>

Thanks,
Florian
Adhemerval Zanella Jan. 15, 2018, 2:26 p.m. | #2
> Il giorno 15 gen 2018, alle ore 11:46, Florian Weimer <fweimer@redhat.com> ha scritto:
> 
>> On 01/12/2018 10:22 AM, Florian Weimer wrote:
>> +/* Test that throwing C++ exceptions works with the minimum stack size.
> 
> Any comments on this new test?
> 
> <https://sourceware.org/ml/libc-alpha/2018-01/msg00438.html>

LGTM, just curious why you need the noclone and weak alias on do_throw_exception.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>

> 
> Thanks,
> Florian
Florian Weimer Jan. 15, 2018, 2:29 p.m. | #3
On 01/15/2018 03:26 PM, Adhemerval Zanella wrote:
> 
> 
>> Il giorno 15 gen 2018, alle ore 11:46, Florian Weimer <fweimer@redhat.com> ha scritto:
>>
>>> On 01/12/2018 10:22 AM, Florian Weimer wrote:
>>> +/* Test that throwing C++ exceptions works with the minimum stack size.
>>
>> Any comments on this new test?
>>
>> <https://sourceware.org/ml/libc-alpha/2018-01/msg00438.html>
> 
> LGTM, just curious why you need the noclone and weak alias on do_throw_exception.

It's the most reliable way known to me to write a function-level 
compiler barrier.

> Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>

Thanks,
Florian
Adam Sampson Jan. 15, 2018, 11:57 p.m. | #4
Hi Florian,

Florian Weimer <fweimer@redhat.com> writes:

>> +/* Test that throwing C++ exceptions works with the minimum stack size.
> Any comments on this new test?

It causes a build failure for me on the 2.26 branch with GCC 7.2.0 on
x86-64:

g++ tst-minstack-throw.cc -c -I/src/sys/glibc/work/build/ -isystem /gar/packages/gcc-7.2.0/bin/../lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../include/c++/7.2.0 -isystem /gar/packages/gcc-7.2.0/bin/../lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../include/c++/7.2.0/x86_64-pc-linux-gnu -isystem /gar/packages/gcc-7.2.0/bin/../lib/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../include/c++/7.2.0/backward -O2 -Wall -Werror -Wundef -Wwrite-strings -fmerge-all-constants -fno-stack-protector -frounding-math -g         -I../include -I/src/sys/glibc/work/build/nptl  -I/src/sys/glibc/work/build  -I../sysdeps/unix/sysv/linux/x86_64/64  -I../sysdeps/unix/sysv/linux/x86_64  -I../sysdeps/unix/sysv/linux/x86  -I../sysdeps/x86/nptl  -I../sysdeps/unix/sysv/linux/wordsize-64  -I../sysdeps/x86_64/nptl  -I../sysdeps/unix/sysv/linux/include -I../sysdeps/unix/sysv/linux  -I../sysdeps/nptl  -I../sysdeps/pthread  -I../sysdeps/gnu  -I../sysdeps/unix/inet  -I../sysdeps/unix/sysv  -I../sysdeps/unix/x86_64  -I../sysdeps/unix  -I../sysdeps/posix  -I../sysdeps/x86_64/64  -I../sysdeps/x86_64/fpu/multiarch  -I../sysdeps/x86_64/fpu  -I../sysdeps/x86/fpu/include -I../sysdeps/x86/fpu  -I../sysdeps/x86_64/multiarch  -I../sysdeps/x86_64  -I../sysdeps/x86  -I../sysdeps/ieee754/float128  -I../sysdeps/ieee754/ldbl-96/include -I../sysdeps/ieee754/ldbl-96  -I../sysdeps/ieee754/dbl-64/wordsize-64  -I../sysdeps/ieee754/dbl-64  -I../sysdeps/ieee754/flt-32  -I../sysdeps/wordsize-64  -I../sysdeps/ieee754  -I../sysdeps/generic  -I.. -I../libio -I. -nostdinc -isystem /gar/packages/gcc-7.2.0/bin/../lib/gcc/x86_64-pc-linux-gnu/7.2.0/include -isystem /gar/packages/gcc-7.2.0/bin/../lib/gcc/x86_64-pc-linux-gnu/7.2.0/include-fixed -isystem /gar/include -isystem /gar/include  -D_LIBC_REENTRANT -include /src/sys/glibc/work/build/libc-modules.h -DMODULE_NAME=testsuite -include ../include/libc-symbols.h       -DTOP_NAMESPACE=glibc -o /src/sys/glibc/work/build/nptl/tst-minstack-throw.o -MD -MP -MF /src/sys/glibc/work/build/nptl/tst-minstack-throw.o.dt -MT /src/sys/glibc/work/build/nptl/tst-minstack-throw.o
tst-minstack-throw.cc:69:7: error: identifier 'static_assert' is a keyword in C++11 [-Werror=c++11-compat]
       TEST_COMPARE (strcmp (e.what (), "test exception"), 0);
       ^~~~~~~~~~~~
In file included from tst-minstack-throw.cc:23:0:
tst-minstack-throw.cc: In function 'void* threadfunc(void*)':
../support/check.h:91:32: error: 'static_assert' was not declared in this scope
 # define support_static_assert static_assert
                                ^
../support/check.h:108:5: note: in expansion of macro 'support_static_assert'
     support_static_assert ((__left_type) 1.0 == (__left_type) 1.5,      \
     ^~~~~~~~~~~~~~~~~~~~~
tst-minstack-throw.cc:69:7: note: in expansion of macro 'TEST_COMPARE'
       TEST_COMPARE (strcmp (e.what (), "test exception"), 0);
       ^~~~~~~~~~~~
cc1plus: all warnings being treated as errors

Thanks,
Florian Weimer Jan. 16, 2018, 8:38 a.m. | #5
On 01/16/2018 12:57 AM, Adam Sampson wrote:
> It causes a build failure for me on the 2.26 branch with GCC 7.2.0 on
> x86-64:

Should now be fixed.

Thanks,
Florian

Patch

diff --git a/nptl/Makefile b/nptl/Makefile
index 12c69f99d8..d59caa5980 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -231,6 +231,7 @@  CFLAGS-tst-thread_local1.o = -std=gnu++11
 LDLIBS-tst-thread_local1 = -lstdc++
 CFLAGS-tst-thread-exit-clobber.o = -std=gnu++11
 LDLIBS-tst-thread-exit-clobber = -lstdc++
+LDLIBS-tst-minstack-throw = -lstdc++
 
 tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
 	tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \
@@ -307,7 +308,8 @@  tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
 	tst-bad-schedattr \
 	tst-thread_local1 tst-mutex-errorcheck tst-robust10 \
 	tst-robust-fork tst-create-detached tst-memstream \
-	tst-thread-exit-clobber tst-minstack-cancel tst-minstack-exit
+	tst-thread-exit-clobber tst-minstack-cancel tst-minstack-exit \
+	tst-minstack-throw
 
 tests-internal := tst-rwlock19 tst-rwlock20 \
 		  tst-sem11 tst-sem12 tst-sem13 \
@@ -457,7 +459,8 @@  endif
 
 ifeq (,$(CXX))
 # These tests require a C++ compiler and runtime.
-tests-unsupported += tst-cancel24 tst-cancel24-static tst-once5
+tests-unsupported += tst-cancel24 tst-cancel24-static tst-once5 \
+  tst-minstack-throw
 endif
 # These tests require a C++ compiler and runtime with thread_local support.
 ifneq ($(have-cxx-thread_local),yes)
diff --git a/nptl/tst-minstack-throw.cc b/nptl/tst-minstack-throw.cc
new file mode 100644
index 0000000000..b0a897b0c6
--- /dev/null
+++ b/nptl/tst-minstack-throw.cc
@@ -0,0 +1,87 @@ 
+/* Test that throwing C++ exceptions works with the minimum stack size.
+   Copyright (C) 2018 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 <stdexcept>
+
+#include <limits.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/xthread.h>
+
+/* Throw a std::runtime_exception.  */
+__attribute__ ((noinline, noclone, weak))
+void
+do_throw_exception ()
+{
+  throw std::runtime_error ("test exception");
+}
+
+/* Class with a destructor, to trigger unwind handling.  */
+struct class_with_destructor
+{
+  class_with_destructor ();
+  ~class_with_destructor ();
+};
+
+__attribute__ ((noinline, noclone, weak))
+class_with_destructor::class_with_destructor ()
+{
+}
+
+__attribute__ ((noinline, noclone, weak))
+class_with_destructor::~class_with_destructor ()
+{
+}
+
+__attribute__ ((noinline, noclone, weak))
+void
+function_with_destructed_object ()
+{
+  class_with_destructor obj;
+  do_throw_exception ();
+}
+
+static void *
+threadfunc (void *closure)
+{
+  try
+    {
+      function_with_destructed_object ();
+      FAIL_EXIT1 ("no exception thrown");
+    }
+  catch (std::exception &e)
+    {
+      TEST_COMPARE (strcmp (e.what (), "test exception"), 0);
+      return reinterpret_cast<void *> (threadfunc);
+    }
+  FAIL_EXIT1 ("no exception caught");
+}
+
+static int
+do_test (void)
+{
+  pthread_attr_t attr;
+  xpthread_attr_init (&attr);
+  xpthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
+  pthread_t thr = xpthread_create (&attr, threadfunc, NULL);
+  TEST_VERIFY (xpthread_join (thr) == threadfunc);
+  xpthread_attr_destroy (&attr);
+  return 0;
+}
+
+#include <support/test-driver.c>