From 755be51d0266bc008def4de484cc9c7803283d69 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 4 Dec 2015 17:32:40 +0000 Subject: [PATCH] PR libstdc++/57060 cope with invalid thread IDs PR libstdc++/57060 * include/std/thread (operator==(thread::id, thread::id)): Do not use __gthread_equal. (operator<(thread::id, thread::id)): Add comment. (this_thread::get_id()): Do not use __gthread_self for single-threaded programs using glibc. * testsuite/30_threads/this_thread/57060.cc: New. From-SVN: r231289 --- libstdc++-v3/ChangeLog | 10 +++++ libstdc++-v3/include/std/thread | 27 ++++++++++++-- .../testsuite/30_threads/this_thread/57060.cc | 37 +++++++++++++++++++ 3 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 libstdc++-v3/testsuite/30_threads/this_thread/57060.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index eafe38c7ca1..f77428e1b2f 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,13 @@ +2015-12-04 Jonathan Wakely + + PR libstdc++/57060 + * include/std/thread (operator==(thread::id, thread::id)): Do not use + __gthread_equal. + (operator<(thread::id, thread::id)): Add comment. + (this_thread::get_id()): Do not use __gthread_self for single-threaded + programs using glibc. + * testsuite/30_threads/this_thread/57060.cc: New. + 2015-12-02 Jonathan Wakely PR libstdc++/56383 diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread index 8c01feb7927..efdd83e75f7 100644 --- a/libstdc++-v3/include/std/thread +++ b/libstdc++-v3/include/std/thread @@ -89,11 +89,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION friend bool operator==(thread::id __x, thread::id __y) noexcept - { return __gthread_equal(__x._M_thread, __y._M_thread); } + { + // pthread_equal is undefined if either thread ID is not valid, so we + // can't safely use __gthread_equal on default-constructed values (nor + // the non-zero value returned by this_thread::get_id() for + // single-threaded programs using GNU libc). Assume EqualityComparable. + return __x._M_thread == __y._M_thread; + } friend bool operator<(thread::id __x, thread::id __y) noexcept - { return __x._M_thread < __y._M_thread; } + { + // Pthreads doesn't define any way to do this, so we just have to + // assume native_handle_type is LessThanComparable. + return __x._M_thread < __y._M_thread; + } template friend basic_ostream<_CharT, _Traits>& @@ -269,7 +279,18 @@ _GLIBCXX_END_NAMESPACE_VERSION /// get_id inline thread::id - get_id() noexcept { return thread::id(__gthread_self()); } + get_id() noexcept + { +#ifdef __GLIBC__ + // For the GNU C library pthread_self() is usable without linking to + // libpthread.so but returns 0, so we cannot use it in single-threaded + // programs, because this_thread::get_id() != thread::id{} must be true. + // We know that pthread_t is an integral type in the GNU C library. + if (!__gthread_active_p()) + return thread::id(1); +#endif + return thread::id(__gthread_self()); + } /// yield inline void diff --git a/libstdc++-v3/testsuite/30_threads/this_thread/57060.cc b/libstdc++-v3/testsuite/30_threads/this_thread/57060.cc new file mode 100644 index 00000000000..c9327192742 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/this_thread/57060.cc @@ -0,0 +1,37 @@ +// Copyright (C) 2015 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 +// . + +// { dg-do run { target *-*-gnu* } } +// { dg-options "-std=gnu++11" } +// { dg-require-gthreads "" } + +// N.B. this test intentionally does *not* use -pthread + +#include +#include + +void +test01() +{ + VERIFY( std::this_thread::get_id() != std::thread::id() ); +} + +int +main() +{ + test01(); +} -- 2.30.2