diff --git a/libstdc++-v3/config/os/gnu-linux/os_defines.h b/libstdc++-v3/config/os/gnu-linux/os_defines.h index f821486ec8f5a7cf37ceae3edbe7d239fcf51a02..01bfa9ddd4f28419f41e6106249e3cecb8fe76a6 100644 --- a/libstdc++-v3/config/os/gnu-linux/os_defines.h +++ b/libstdc++-v3/config/os/gnu-linux/os_defines.h @@ -49,4 +49,16 @@ // version dynamically in case it has changed since libstdc++ was configured. #define _GLIBCXX_NO_OBSOLETE_ISINF_ISNAN_DYNAMIC __GLIBC_PREREQ(2,23) +#if __GLIBC_PREREQ(2, 27) +// Since glibc 2.27 pthread_self() is usable without linking to libpthread. +# define _GLIBCXX_NATIVE_THREAD_ID pthread_self() +#else +// Before then it was in libc.so.6 but not libc.a, and always returns 0, +// which breaks the invariant this_thread::get_id() != thread::id{}. +// So only use it if we know the libpthread version is available. +// Otherwise use (__gthread_t)1 as the ID of the main (and only) thread. +# define _GLIBCXX_NATIVE_THREAD_ID \ + (__gthread_active_p() ? __gthread_self() : (__gthread_t)1) +#endif + #endif diff --git a/libstdc++-v3/include/bits/std_thread.h b/libstdc++-v3/include/bits/std_thread.h index 96c8d1bb19ff0b93e29a19c20d611a4cf191b027..24bd5fbd44e8e8f1c6970a88c1242d21398c8694 100644 --- a/libstdc++-v3/include/bits/std_thread.h +++ b/libstdc++-v3/include/bits/std_thread.h @@ -294,26 +294,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline thread::id get_id() noexcept { -#ifdef _GLIBCXX_HAS_GTHREADS - -#ifdef __GLIBC__ - // For the GNU C library pthread_self() is usable without linking to - // libpthread, but prior to version 2.27 the version in libc returns 0, - // which breaks the invariant this_thread::get_id() != thread::id{}. - // - // We know that pthread_t is a scalar type in the GNU C library, - // so just use (__gthread_t)1 as the ID of the main (and only) thread. - // - // This uses __gthread_active_p not __gnu_cxx::__is_single_threaded - // because we don't want the thread::id of the main thread to change - // if additional threads are created later. - if (!__gthread_active_p()) - return thread::id((__gthread_t)1); -#endif - - return thread::id(__gthread_self()); -#else +#ifndef _GLIBCXX_HAS_GTHREADS return thread::id(1); +#elif defined _GLIBCXX_NATIVE_THREAD_ID + return thread::id(_GLIBCXX_NATIVE_THREAD_ID); +#else + return thread::id(__gthread_self()); #endif } diff --git a/libstdc++-v3/testsuite/30_threads/jthread/95989.cc b/libstdc++-v3/testsuite/30_threads/jthread/95989.cc new file mode 100644 index 0000000000000000000000000000000000000000..46444b5ccabcaffd468431084c8786743cb601b8 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/jthread/95989.cc @@ -0,0 +1,54 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This 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 General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } +// { dg-require-gthreads {} } +// { dg-additional-options "-pthread" { target pthread } } +// { dg-additional-options "-static" { target static } } + +#include <thread> + +// PR libstdc++/95989 +// Segfault compiling with static libraries and using jthread::request_stop + +void +test01() +{ + std::jthread t{ [] () {} }; +} + +void +test02() +{ + std::jthread t{ [] () {} }; + t.request_stop(); +} + +void +test03() +{ + std::jthread t{ [] {} }; + std::stop_callback cb(t.get_stop_token(), [] () {}); +} + +int +main() +{ + test01(); + test01(); +} diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/95989.cc b/libstdc++-v3/testsuite/30_threads/this_thread/95989.cc new file mode 100644 index 0000000000000000000000000000000000000000..16535af8b7432944726ea8420d77a5d7f443993a --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/this_thread/95989.cc @@ -0,0 +1,51 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This 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 General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-do run { target c++11 } } +// { dg-require-gthreads {} } +// { dg-additional-options "-pthread" { target pthread } } +// { dg-additional-options "-static" { target static } } + +#include <thread> +#include <testsuite_hooks.h> + +__attribute__((noinline,noipa)) +void +join(std::thread& t) +{ + if (!t.joinable()) + return; + + // Using thread::join() creates a dependency on libpthread symbols + // so that __gthread_active_p is true, and we use pthread_self. + t.join(); +} + +void +test01() +{ + std::thread t; + // PR libstdc++/95989 + auto id = std::this_thread::get_id(); + VERIFY (t.get_id() != id ); +} + +int +main() +{ + test01(); +}