[RFC] libstdc++: Do not use pthread_mutex_clocklock with ThreadSanitizer

Message ID 20230510112009.633444-1-jwakely@redhat.com
State Accepted
Headers
Series [RFC] libstdc++: Do not use pthread_mutex_clocklock with ThreadSanitizer |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Jonathan Wakely May 10, 2023, 11:20 a.m. UTC
  This patch would avoid TSan false positives when using timed waiting
functions on mutexes and condvars, but as noted below, it changes the
semantics.

I'm not sure whether we want this workaround in place until tsan gets
fixed.

On one hand, there's no guarantee that those functions use the right
clock anyway (and they won't do unless a recent-ish glibc is used). But
on the other hand, if they normally would use the right clock because
you have glibc support, it's not ideal for tsan to cause a different
clock to be used.

-- >8 --

As noted in https://github.com/llvm/llvm-project/issues/62623 there are
no tsan interceptors for the new POSIX-1:202x APIs added by
https://austingroupbugs.net/view.php?id=1216 so tsan gives false
positive warnings.

Disable the uses of the new APIs when tsan is active. This changes the
semantics of those functions, because it can change which clock is used
for the wait. This means those functions might be affected by system
clock adjustments when tsan is used, when they would not be affected
otherwise.

libstdc++-v3/ChangeLog:

	* acinclude.m4 (GLIBCXX_CHECK_PTHREAD_COND_CLOCKWAIT): Define
	_GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT to depend on _GLIBCXX_TSAN.
	(GLIBCXX_CHECK_PTHREAD_MUTEX_CLOCKLOCK): Likewise for
	_GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK.
	(GLIBCXX_CHECK_PTHREAD_RWLOCK_CLOCKLOCK): Likewise for
	_GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK.
	* configure: Regenerate.
---
 libstdc++-v3/acinclude.m4 | 6 +++---
 libstdc++-v3/configure    | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)
  

Comments

Jonathan Wakely May 10, 2023, 11:31 a.m. UTC | #1
On Wed, 10 May 2023 at 12:20, Jonathan Wakely via Libstdc++ <
libstdc++@gcc.gnu.org> wrote:

> This patch would avoid TSan false positives when using timed waiting
> functions on mutexes and condvars, but as noted below, it changes the
> semantics.
>
> I'm not sure whether we want this workaround in place until tsan gets
> fixed.
>
> On one hand, there's no guarantee that those functions use the right
> clock anyway (and they won't do unless a recent-ish glibc is used). But
> on the other hand, if they normally would use the right clock because
> you have glibc support, it's not ideal for tsan to cause a different
> clock to be used.
>

But of course, it's not ideal to get false positives from tsan either
(especially when it looks like a libstdc++ bug, as initially reported to
me).



>
> -- >8 --
>
> As noted in https://github.com/llvm/llvm-project/issues/62623 there are
> no tsan interceptors for the new POSIX-1:202x APIs added by
> https://austingroupbugs.net/view.php?id=1216 so tsan gives false
> positive warnings.
>
> Disable the uses of the new APIs when tsan is active. This changes the
> semantics of those functions, because it can change which clock is used
> for the wait. This means those functions might be affected by system
> clock adjustments when tsan is used, when they would not be affected
> otherwise.
>
> libstdc++-v3/ChangeLog:
>
>         * acinclude.m4 (GLIBCXX_CHECK_PTHREAD_COND_CLOCKWAIT): Define
>         _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT to depend on _GLIBCXX_TSAN.
>         (GLIBCXX_CHECK_PTHREAD_MUTEX_CLOCKLOCK): Likewise for
>         _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK.
>         (GLIBCXX_CHECK_PTHREAD_RWLOCK_CLOCKLOCK): Likewise for
>         _GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK.
>         * configure: Regenerate.
> ---
>  libstdc++-v3/acinclude.m4 | 6 +++---
>  libstdc++-v3/configure    | 6 +++---
>  2 files changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
> index 89e7f5f5f45..e2700b05ec3 100644
> --- a/libstdc++-v3/acinclude.m4
> +++ b/libstdc++-v3/acinclude.m4
> @@ -4284,7 +4284,7 @@ AC_DEFUN([GLIBCXX_CHECK_PTHREAD_COND_CLOCKWAIT], [
>        [glibcxx_cv_PTHREAD_COND_CLOCKWAIT=no])
>    ])
>    if test $glibcxx_cv_PTHREAD_COND_CLOCKWAIT = yes; then
> -    AC_DEFINE(_GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT, 1, [Define if
> pthread_cond_clockwait is available in <pthread.h>.])
> +    AC_DEFINE(_GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT, (_GLIBCXX_TSAN==0),
> [Define if pthread_cond_clockwait is available in <pthread.h>.])
>    fi
>
>    CXXFLAGS="$ac_save_CXXFLAGS"
> @@ -4314,7 +4314,7 @@ AC_DEFUN([GLIBCXX_CHECK_PTHREAD_MUTEX_CLOCKLOCK], [
>        [glibcxx_cv_PTHREAD_MUTEX_CLOCKLOCK=no])
>    ])
>    if test $glibcxx_cv_PTHREAD_MUTEX_CLOCKLOCK = yes; then
> -    AC_DEFINE(_GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK, 1, [Define if
> pthread_mutex_clocklock is available in <pthread.h>.])
> +    AC_DEFINE(_GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK, (_GLIBCXX_TSAN==0),
> [Define if pthread_mutex_clocklock is available in <pthread.h>.])
>    fi
>
>    CXXFLAGS="$ac_save_CXXFLAGS"
> @@ -4346,7 +4346,7 @@ AC_DEFUN([GLIBCXX_CHECK_PTHREAD_RWLOCK_CLOCKLOCK], [
>        [glibcxx_cv_PTHREAD_RWLOCK_CLOCKLOCK=no])
>    ])
>    if test $glibcxx_cv_PTHREAD_RWLOCK_CLOCKLOCK = yes; then
> -    AC_DEFINE(_GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK, 1, [Define if
> pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock are available in
> <pthread.h>.])
> +    AC_DEFINE(_GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK, (_GLIBCXX_TSAN==0),
> [Define if pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock are
> available in <pthread.h>.])
>    fi
>
>    CXXFLAGS="$ac_save_CXXFLAGS"
>
>
  
Mike Crowe May 11, 2023, 12:19 p.m. UTC | #2
On Wednesday 10 May 2023 at 12:31:12 +0100, Jonathan Wakely wrote:
> On Wed, 10 May 2023 at 12:20, Jonathan Wakely via Libstdc++ <
> libstdc++@gcc.gnu.org> wrote:
> 
> > This patch would avoid TSan false positives when using timed waiting
> > functions on mutexes and condvars, but as noted below, it changes the
> > semantics.
> >
> > I'm not sure whether we want this workaround in place until tsan gets
> > fixed.
> >
> > On one hand, there's no guarantee that those functions use the right
> > clock anyway (and they won't do unless a recent-ish glibc is used). But
> > on the other hand, if they normally would use the right clock because
> > you have glibc support, it's not ideal for tsan to cause a different
> > clock to be used.
> >
> 
> But of course, it's not ideal to get false positives from tsan either
> (especially when it looks like a libstdc++ bug, as initially reported to
> me).

I think that this is probably the least-worst option in the short term. As
TSan is distributed with GCC this workaround can be removed as soon as its
TSan implementation gains the necessary interceptors. I shall look into
trying to do that.

However, ...

> > diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
> > index 89e7f5f5f45..e2700b05ec3 100644
> > --- a/libstdc++-v3/acinclude.m4
> > +++ b/libstdc++-v3/acinclude.m4
> > @@ -4284,7 +4284,7 @@ AC_DEFUN([GLIBCXX_CHECK_PTHREAD_COND_CLOCKWAIT], [
> >        [glibcxx_cv_PTHREAD_COND_CLOCKWAIT=no])
> >    ])
> >    if test $glibcxx_cv_PTHREAD_COND_CLOCKWAIT = yes; then
> > -    AC_DEFINE(_GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT, 1, [Define if
> > pthread_cond_clockwait is available in <pthread.h>.])
> > +    AC_DEFINE(_GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT, (_GLIBCXX_TSAN==0),
> > [Define if pthread_cond_clockwait is available in <pthread.h>.])
> >    fi

TSan does appear to have an interceptor for pthread_cond_clockwait, even if
it lacks the others. Does this mean that this part is unnecessary?

See: https://github.com/google/sanitizers/issues/1259

Thanks.

Mike.
  
Jonathan Wakely May 11, 2023, 12:42 p.m. UTC | #3
On Thu, 11 May 2023 at 13:19, Mike Crowe <mac@mcrowe.com> wrote:

> On Wednesday 10 May 2023 at 12:31:12 +0100, Jonathan Wakely wrote:
> > On Wed, 10 May 2023 at 12:20, Jonathan Wakely via Libstdc++ <
> > libstdc++@gcc.gnu.org> wrote:
> >
> > > This patch would avoid TSan false positives when using timed waiting
> > > functions on mutexes and condvars, but as noted below, it changes the
> > > semantics.
> > >
> > > I'm not sure whether we want this workaround in place until tsan gets
> > > fixed.
> > >
> > > On one hand, there's no guarantee that those functions use the right
> > > clock anyway (and they won't do unless a recent-ish glibc is used). But
> > > on the other hand, if they normally would use the right clock because
> > > you have glibc support, it's not ideal for tsan to cause a different
> > > clock to be used.
> > >
> >
> > But of course, it's not ideal to get false positives from tsan either
> > (especially when it looks like a libstdc++ bug, as initially reported to
> > me).
>
> I think that this is probably the least-worst option in the short term. As
> TSan is distributed with GCC this workaround can be removed as soon as its
> TSan implementation gains the necessary interceptors. I shall look into
> trying to do that.
>

Right, and before it gets into GCC it will already be upstream in LLVM, so
a recent Clang would support it too by the time we changed anything in
libstdc++.

Another option would be just document how to use
https://github.com/google/sanitizers/wiki/ThreadSanitizerSuppressions for
runtime suppressions, but that would be far from ideal.




> However, ...
>
> > > diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
> > > index 89e7f5f5f45..e2700b05ec3 100644
> > > --- a/libstdc++-v3/acinclude.m4
> > > +++ b/libstdc++-v3/acinclude.m4
> > > @@ -4284,7 +4284,7 @@ AC_DEFUN([GLIBCXX_CHECK_PTHREAD_COND_CLOCKWAIT],
> [
> > >        [glibcxx_cv_PTHREAD_COND_CLOCKWAIT=no])
> > >    ])
> > >    if test $glibcxx_cv_PTHREAD_COND_CLOCKWAIT = yes; then
> > > -    AC_DEFINE(_GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT, 1, [Define if
> > > pthread_cond_clockwait is available in <pthread.h>.])
> > > +    AC_DEFINE(_GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT, (_GLIBCXX_TSAN==0),
> > > [Define if pthread_cond_clockwait is available in <pthread.h>.])
> > >    fi
>
> TSan does appear to have an interceptor for pthread_cond_clockwait, even if
> it lacks the others. Does this mean that this part is unnecessary?
>

Ah good point, thanks. I grepped for clocklock but not clockwait.


>
> See: https://github.com/google/sanitizers/issues/1259
>
>
Thanks, I've added a link to my new tsan issue there.
  
Thomas Rodgers May 11, 2023, 3:54 p.m. UTC | #4
On Thu, May 11, 2023 at 5:21 AM Mike Crowe via Libstdc++ <
libstdc++@gcc.gnu.org> wrote:

> On Wednesday 10 May 2023 at 12:31:12 +0100, Jonathan Wakely wrote:
> > On Wed, 10 May 2023 at 12:20, Jonathan Wakely via Libstdc++ <
> > libstdc++@gcc.gnu.org> wrote:
> >
> > > This patch would avoid TSan false positives when using timed waiting
> > > functions on mutexes and condvars, but as noted below, it changes the
> > > semantics.
> > >
> > > I'm not sure whether we want this workaround in place until tsan gets
> > > fixed.
> > >
> > > On one hand, there's no guarantee that those functions use the right
> > > clock anyway (and they won't do unless a recent-ish glibc is used). But
> > > on the other hand, if they normally would use the right clock because
> > > you have glibc support, it's not ideal for tsan to cause a different
> > > clock to be used.
> > >
> >
> > But of course, it's not ideal to get false positives from tsan either
> > (especially when it looks like a libstdc++ bug, as initially reported to
> > me).
>
> I think that this is probably the least-worst option in the short term. As
> TSan is distributed with GCC this workaround can be removed as soon as its
> TSan implementation gains the necessary interceptors. I shall look into
> trying to do that.
>
>
I don't have a strong opinion either way on this, but I think documenting
the TSAN suppressions is the option most in keeping with the principle of
Least Astonishment.


> However, ...
>
> > > diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
> > > index 89e7f5f5f45..e2700b05ec3 100644
> > > --- a/libstdc++-v3/acinclude.m4
> > > +++ b/libstdc++-v3/acinclude.m4
> > > @@ -4284,7 +4284,7 @@ AC_DEFUN([GLIBCXX_CHECK_PTHREAD_COND_CLOCKWAIT],
> [
> > >        [glibcxx_cv_PTHREAD_COND_CLOCKWAIT=no])
> > >    ])
> > >    if test $glibcxx_cv_PTHREAD_COND_CLOCKWAIT = yes; then
> > > -    AC_DEFINE(_GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT, 1, [Define if
> > > pthread_cond_clockwait is available in <pthread.h>.])
> > > +    AC_DEFINE(_GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT, (_GLIBCXX_TSAN==0),
> > > [Define if pthread_cond_clockwait is available in <pthread.h>.])
> > >    fi
>
> TSan does appear to have an interceptor for pthread_cond_clockwait, even if
> it lacks the others. Does this mean that this part is unnecessary?
>
> See: https://github.com/google/sanitizers/issues/1259
>
> Thanks.
>
> Mike.
>
>
  
Jonathan Wakely May 11, 2023, 4:04 p.m. UTC | #5
On Thu, 11 May 2023 at 16:54, Thomas Rodgers <trodgers@redhat.com> wrote:

>
>
> On Thu, May 11, 2023 at 5:21 AM Mike Crowe via Libstdc++ <
> libstdc++@gcc.gnu.org> wrote:
>
>> On Wednesday 10 May 2023 at 12:31:12 +0100, Jonathan Wakely wrote:
>> > On Wed, 10 May 2023 at 12:20, Jonathan Wakely via Libstdc++ <
>> > libstdc++@gcc.gnu.org> wrote:
>> >
>> > > This patch would avoid TSan false positives when using timed waiting
>> > > functions on mutexes and condvars, but as noted below, it changes the
>> > > semantics.
>> > >
>> > > I'm not sure whether we want this workaround in place until tsan gets
>> > > fixed.
>> > >
>> > > On one hand, there's no guarantee that those functions use the right
>> > > clock anyway (and they won't do unless a recent-ish glibc is used).
>> But
>> > > on the other hand, if they normally would use the right clock because
>> > > you have glibc support, it's not ideal for tsan to cause a different
>> > > clock to be used.
>> > >
>> >
>> > But of course, it's not ideal to get false positives from tsan either
>> > (especially when it looks like a libstdc++ bug, as initially reported to
>> > me).
>>
>> I think that this is probably the least-worst option in the short term. As
>> TSan is distributed with GCC this workaround can be removed as soon as its
>> TSan implementation gains the necessary interceptors. I shall look into
>> trying to do that.
>>
>>
> I don't have a strong opinion either way on this, but I think documenting
> the TSAN suppressions is the option most in keeping with the principle of
> Least Astonishment.
>

That assumes anybody reads the docs :-)
Getting TSan errors from the std::lib is somewhat astonishing. The errors
could be avoided, at the risk of subtle timing differences between
tsanitized and un-tsanitized builds ... but won't there be subtle diffs
anyway based on the TSan overhead? Admittedly those will just be fairly
constant overhead, and so immune to system clock adjustments.
  

Patch

diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 89e7f5f5f45..e2700b05ec3 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -4284,7 +4284,7 @@  AC_DEFUN([GLIBCXX_CHECK_PTHREAD_COND_CLOCKWAIT], [
       [glibcxx_cv_PTHREAD_COND_CLOCKWAIT=no])
   ])
   if test $glibcxx_cv_PTHREAD_COND_CLOCKWAIT = yes; then
-    AC_DEFINE(_GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT, 1, [Define if pthread_cond_clockwait is available in <pthread.h>.])
+    AC_DEFINE(_GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT, (_GLIBCXX_TSAN==0), [Define if pthread_cond_clockwait is available in <pthread.h>.])
   fi
 
   CXXFLAGS="$ac_save_CXXFLAGS"
@@ -4314,7 +4314,7 @@  AC_DEFUN([GLIBCXX_CHECK_PTHREAD_MUTEX_CLOCKLOCK], [
       [glibcxx_cv_PTHREAD_MUTEX_CLOCKLOCK=no])
   ])
   if test $glibcxx_cv_PTHREAD_MUTEX_CLOCKLOCK = yes; then
-    AC_DEFINE(_GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK, 1, [Define if pthread_mutex_clocklock is available in <pthread.h>.])
+    AC_DEFINE(_GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK, (_GLIBCXX_TSAN==0), [Define if pthread_mutex_clocklock is available in <pthread.h>.])
   fi
 
   CXXFLAGS="$ac_save_CXXFLAGS"
@@ -4346,7 +4346,7 @@  AC_DEFUN([GLIBCXX_CHECK_PTHREAD_RWLOCK_CLOCKLOCK], [
       [glibcxx_cv_PTHREAD_RWLOCK_CLOCKLOCK=no])
   ])
   if test $glibcxx_cv_PTHREAD_RWLOCK_CLOCKLOCK = yes; then
-    AC_DEFINE(_GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK, 1, [Define if pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock are available in <pthread.h>.])
+    AC_DEFINE(_GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK, (_GLIBCXX_TSAN==0), [Define if pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock are available in <pthread.h>.])
   fi
 
   CXXFLAGS="$ac_save_CXXFLAGS"