[compiler-rt] r189767 - tsan: properly intercept pthread_cond functions

Dmitry Vyukov dvyukov at google.com
Tue Sep 3 05:36:40 PDT 2013


On Tue, Sep 3, 2013 at 4:19 PM, Alexander Potapenko <glider at google.com> wrote:
> On Tue, Sep 3, 2013 at 4:11 PM, Dmitry Vyukov <dvyukov at google.com> wrote:
>> On Tue, Sep 3, 2013 at 3:37 PM, Alexander Potapenko <glider at google.com> wrote:
>>> Am I right this won't work properly if new versions of
>>> pthread_cond_xxx are introduced or if the user has an old glibc?
>>
>> yes
>>
>>> Can this be checked or at least documented?
>>
>> how can we check it?
> We can probably check whether the 2.3.2 versions are available. If
> they aren't, the glibc is too old.

2.3.2 and 2.2.5 are like 11 years old, I do not want to spent time on
old versions



>> where will such documentation be useful?
> Next time the interface changes we'll spend less time debugging
> spurious pthread_cond_wait behavior if there's a comment about that.

sorry, I meant where should I put the documentation so that it will be useful ?


>>> On Mon, Sep 2, 2013 at 10:06 PM, Dmitry Vyukov <dvyukov at google.com> wrote:
>>>> Author: dvyukov
>>>> Date: Mon Sep  2 13:06:28 2013
>>>> New Revision: 189767
>>>>
>>>> URL: http://llvm.org/viewvc/llvm-project?rev=189767&view=rev
>>>> Log:
>>>> tsan: properly intercept pthread_cond functions
>>>>
>>>> Added:
>>>>     compiler-rt/trunk/lib/tsan/lit_tests/cond_version.c
>>>> Modified:
>>>>     compiler-rt/trunk/lib/interception/interception_linux.cc
>>>>     compiler-rt/trunk/lib/interception/interception_linux.h
>>>>     compiler-rt/trunk/lib/tsan/lit_tests/test_output.sh
>>>>     compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
>>>>     compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc
>>>>     compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h
>>>>
>>>> Modified: compiler-rt/trunk/lib/interception/interception_linux.cc
>>>> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/interception_linux.cc?rev=189767&r1=189766&r2=189767&view=diff
>>>> ==============================================================================
>>>> --- compiler-rt/trunk/lib/interception/interception_linux.cc (original)
>>>> +++ compiler-rt/trunk/lib/interception/interception_linux.cc Mon Sep  2 13:06:28 2013
>>>> @@ -15,7 +15,6 @@
>>>>  #ifdef __linux__
>>>>  #include "interception.h"
>>>>
>>>> -#include <stddef.h>  // for NULL
>>>>  #include <dlfcn.h>   // for dlsym
>>>>
>>>>  namespace __interception {
>>>> @@ -24,6 +23,11 @@ bool GetRealFunctionAddress(const char *
>>>>    *func_addr = (uptr)dlsym(RTLD_NEXT, func_name);
>>>>    return real == wrapper;
>>>>  }
>>>> +
>>>> +void *GetFuncAddrVer(const char *func_name, const char *ver) {
>>>> +  return dlvsym(RTLD_NEXT, func_name, ver);
>>>> +}
>>>> +
>>>>  }  // namespace __interception
>>>>
>>>>
>>>>
>>>> Modified: compiler-rt/trunk/lib/interception/interception_linux.h
>>>> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/interception_linux.h?rev=189767&r1=189766&r2=189767&view=diff
>>>> ==============================================================================
>>>> --- compiler-rt/trunk/lib/interception/interception_linux.h (original)
>>>> +++ compiler-rt/trunk/lib/interception/interception_linux.h Mon Sep  2 13:06:28 2013
>>>> @@ -25,6 +25,7 @@ namespace __interception {
>>>>  // returns true if a function with the given name was found.
>>>>  bool GetRealFunctionAddress(const char *func_name, uptr *func_addr,
>>>>      uptr real, uptr wrapper);
>>>> +void *GetFuncAddrVer(const char *func_name, const char *ver);
>>>>  }  // namespace __interception
>>>>
>>>>  #define INTERCEPT_FUNCTION_LINUX(func) \
>>>> @@ -33,5 +34,10 @@ bool GetRealFunctionAddress(const char *
>>>>            (::__interception::uptr)&(func), \
>>>>            (::__interception::uptr)&WRAP(func))
>>>>
>>>> +#define INTERCEPT_FUNCTION_VER(func, funcver, symver) \
>>>> +    __asm__(".symver "#funcver","#func"@"#symver); \
>>>> +    ::__interception::real_##funcver = (funcver##_f)(unsigned long) \
>>>> +        ::__interception::GetFuncAddrVer(#func, #symver)
>>>> +
>>>>  #endif  // INTERCEPTION_LINUX_H
>>>>  #endif  // __linux__
>>>>
>>>> Added: compiler-rt/trunk/lib/tsan/lit_tests/cond_version.c
>>>> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/cond_version.c?rev=189767&view=auto
>>>> ==============================================================================
>>>> --- compiler-rt/trunk/lib/tsan/lit_tests/cond_version.c (added)
>>>> +++ compiler-rt/trunk/lib/tsan/lit_tests/cond_version.c Mon Sep  2 13:06:28 2013
>>>> @@ -0,0 +1,44 @@
>>>> +// RUN: %clang_tsan -O1 %s -o %t -lrt && %t 2>&1 | FileCheck %s
>>>> +// Test that pthread_cond is properly intercepted,
>>>> +// previously there were issues with versioned symbols.
>>>> +// CHECK: OK
>>>> +
>>>> +#include <stdio.h>
>>>> +#include <stdlib.h>
>>>> +#include <pthread.h>
>>>> +#include <time.h>
>>>> +#include <errno.h>
>>>> +
>>>> +int main() {
>>>> +  typedef unsigned long long u64;
>>>> +  pthread_mutex_t m;
>>>> +  pthread_cond_t c;
>>>> +  pthread_condattr_t at;
>>>> +  struct timespec ts0, ts1, ts2;
>>>> +  int res;
>>>> +  u64 sleep;
>>>> +
>>>> +  pthread_mutex_init(&m, 0);
>>>> +  pthread_condattr_init(&at);
>>>> +  pthread_condattr_setclock(&at, CLOCK_MONOTONIC);
>>>> +  pthread_cond_init(&c, &at);
>>>> +
>>>> +  clock_gettime(CLOCK_MONOTONIC, &ts0);
>>>> +  ts1 = ts0;
>>>> +  ts1.tv_sec += 2;
>>>> +
>>>> +  pthread_mutex_lock(&m);
>>>> +  do {
>>>> +    res = pthread_cond_timedwait(&c, &m, &ts1);
>>>> +  } while (res == 0);
>>>> +  pthread_mutex_unlock(&m);
>>>> +
>>>> +  clock_gettime(CLOCK_MONOTONIC, &ts2);
>>>> +  sleep = (u64)ts2.tv_sec * 1000000000 + ts2.tv_nsec -
>>>> +      ((u64)ts0.tv_sec * 1000000000 + ts0.tv_nsec);
>>>> +  if (res != ETIMEDOUT)
>>>> +    exit(printf("bad return value %d, want %d\n", res, ETIMEDOUT));
>>>> +  if (sleep < 1000000000)
>>>> +    exit(printf("bad sleep duration %lluns, want %dns\n", sleep, 1000000000));
>>>> +  fprintf(stderr, "OK\n");
>>>> +}
>>>>
>>>> Modified: compiler-rt/trunk/lib/tsan/lit_tests/test_output.sh
>>>> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/lit_tests/test_output.sh?rev=189767&r1=189766&r2=189767&view=diff
>>>> ==============================================================================
>>>> --- compiler-rt/trunk/lib/tsan/lit_tests/test_output.sh (original)
>>>> +++ compiler-rt/trunk/lib/tsan/lit_tests/test_output.sh Mon Sep  2 13:06:28 2013
>>>> @@ -13,7 +13,7 @@ BLACKLIST=$ROOTDIR/lit_tests/Helpers/bla
>>>>
>>>>  # TODO: add testing for all of -O0...-O3
>>>>  CFLAGS="-fsanitize=thread -fsanitize-blacklist=$BLACKLIST -fPIE -O1 -g -Wall"
>>>> -LDFLAGS="-pie -lpthread -ldl $ROOTDIR/rtl/libtsan.a"
>>>> +LDFLAGS="-pie -lpthread -ldl -lrt $ROOTDIR/rtl/libtsan.a"
>>>>
>>>>  test_file() {
>>>>    SRC=$1
>>>>
>>>> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
>>>> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=189767&r1=189766&r2=189767&view=diff
>>>> ==============================================================================
>>>> --- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
>>>> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Mon Sep  2 13:06:28 2013
>>>> @@ -1051,46 +1051,43 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_unl
>>>>    return res;
>>>>  }
>>>>
>>>> -// libpthread.so contains several versions of pthread_cond_init symbol.
>>>> -// When we just dlsym() it, we get the wrong (old) version.
>>>> -/*
>>>> -TSAN_INTERCEPTOR(int, pthread_cond_init, void *c, void *a) {
>>>> -  SCOPED_TSAN_INTERCEPTOR(pthread_cond_init, c, a);
>>>> -  int res = REAL(pthread_cond_init)(c, a);
>>>> +TSAN_INTERCEPTOR(int, pthread_cond_init_2_3_2, void *c, void *a) {
>>>> +  SCOPED_TSAN_INTERCEPTOR(pthread_cond_init_2_3_2, c, a);
>>>> +  int res = REAL(pthread_cond_init_2_3_2)(c, a);
>>>>    return res;
>>>>  }
>>>> -*/
>>>>
>>>> -TSAN_INTERCEPTOR(int, pthread_cond_destroy, void *c) {
>>>> -  SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy, c);
>>>> -  int res = REAL(pthread_cond_destroy)(c);
>>>> +TSAN_INTERCEPTOR(int, pthread_cond_destroy_2_3_2, void *c) {
>>>> +  SCOPED_TSAN_INTERCEPTOR(pthread_cond_destroy_2_3_2, c);
>>>> +  int res = REAL(pthread_cond_destroy_2_3_2)(c);
>>>>    return res;
>>>>  }
>>>>
>>>> -TSAN_INTERCEPTOR(int, pthread_cond_signal, void *c) {
>>>> -  SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal, c);
>>>> -  int res = REAL(pthread_cond_signal)(c);
>>>> +TSAN_INTERCEPTOR(int, pthread_cond_signal_2_3_2, void *c) {
>>>> +  SCOPED_TSAN_INTERCEPTOR(pthread_cond_signal_2_3_2, c);
>>>> +  int res = REAL(pthread_cond_signal_2_3_2)(c);
>>>>    return res;
>>>>  }
>>>>
>>>> -TSAN_INTERCEPTOR(int, pthread_cond_broadcast, void *c) {
>>>> -  SCOPED_TSAN_INTERCEPTOR(pthread_cond_broadcast, c);
>>>> -  int res = REAL(pthread_cond_broadcast)(c);
>>>> +TSAN_INTERCEPTOR(int, pthread_cond_broadcast_2_3_2, void *c) {
>>>> +  SCOPED_TSAN_INTERCEPTOR(pthread_cond_broadcast_2_3_2, c);
>>>> +  int res = REAL(pthread_cond_broadcast_2_3_2)(c);
>>>>    return res;
>>>>  }
>>>>
>>>> -TSAN_INTERCEPTOR(int, pthread_cond_wait, void *c, void *m) {
>>>> -  SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait, c, m);
>>>> +TSAN_INTERCEPTOR(int, pthread_cond_wait_2_3_2, void *c, void *m) {
>>>> +  SCOPED_TSAN_INTERCEPTOR(pthread_cond_wait_2_3_2, c, m);
>>>>    MutexUnlock(thr, pc, (uptr)m);
>>>> -  int res = REAL(pthread_cond_wait)(c, m);
>>>> +  int res = REAL(pthread_cond_wait_2_3_2)(c, m);
>>>>    MutexLock(thr, pc, (uptr)m);
>>>>    return res;
>>>>  }
>>>>
>>>> -TSAN_INTERCEPTOR(int, pthread_cond_timedwait, void *c, void *m, void *abstime) {
>>>> -  SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait, c, m, abstime);
>>>> +TSAN_INTERCEPTOR(int, pthread_cond_timedwait_2_3_2, void *c, void *m,
>>>> +    void *abstime) {
>>>> +  SCOPED_TSAN_INTERCEPTOR(pthread_cond_timedwait_2_3_2, c, m, abstime);
>>>>    MutexUnlock(thr, pc, (uptr)m);
>>>> -  int res = REAL(pthread_cond_timedwait)(c, m, abstime);
>>>> +  int res = REAL(pthread_cond_timedwait_2_3_2)(c, m, abstime);
>>>>    MutexLock(thr, pc, (uptr)m);
>>>>    return res;
>>>>  }
>>>> @@ -1984,12 +1981,18 @@ void InitializeInterceptors() {
>>>>    TSAN_INTERCEPT(pthread_rwlock_timedwrlock);
>>>>    TSAN_INTERCEPT(pthread_rwlock_unlock);
>>>>
>>>> -  // TSAN_INTERCEPT(pthread_cond_init);
>>>> -  TSAN_INTERCEPT(pthread_cond_destroy);
>>>> -  TSAN_INTERCEPT(pthread_cond_signal);
>>>> -  TSAN_INTERCEPT(pthread_cond_broadcast);
>>>> -  TSAN_INTERCEPT(pthread_cond_wait);
>>>> -  TSAN_INTERCEPT(pthread_cond_timedwait);
>>>> +  INTERCEPT_FUNCTION_VER(pthread_cond_init, pthread_cond_init_2_3_2,
>>>> +      GLIBC_2.3.2);
>>>> +  INTERCEPT_FUNCTION_VER(pthread_cond_destroy, pthread_cond_destroy_2_3_2,
>>>> +      GLIBC_2.3.2);
>>>> +  INTERCEPT_FUNCTION_VER(pthread_cond_signal, pthread_cond_signal_2_3_2,
>>>> +      GLIBC_2.3.2);
>>>> +  INTERCEPT_FUNCTION_VER(pthread_cond_broadcast, pthread_cond_broadcast_2_3_2,
>>>> +      GLIBC_2.3.2);
>>>> +  INTERCEPT_FUNCTION_VER(pthread_cond_wait, pthread_cond_wait_2_3_2,
>>>> +      GLIBC_2.3.2);
>>>> +  INTERCEPT_FUNCTION_VER(pthread_cond_timedwait, pthread_cond_timedwait_2_3_2,
>>>> +      GLIBC_2.3.2);
>>>>
>>>>    TSAN_INTERCEPT(pthread_barrier_init);
>>>>    TSAN_INTERCEPT(pthread_barrier_destroy);
>>>>
>>>> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc
>>>> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc?rev=189767&r1=189766&r2=189767&view=diff
>>>> ==============================================================================
>>>> --- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc (original)
>>>> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc Mon Sep  2 13:06:28 2013
>>>> @@ -169,12 +169,15 @@ void StatOutput(u64 *stat) {
>>>>    name[StatInt_pthread_rwlock_timedwrlock]
>>>>                                           = "  pthread_rwlock_timedwrlock      ";
>>>>    name[StatInt_pthread_rwlock_unlock]    = "  pthread_rwlock_unlock           ";
>>>> -  name[StatInt_pthread_cond_init]        = "  pthread_cond_init               ";
>>>> -  name[StatInt_pthread_cond_destroy]     = "  pthread_cond_destroy            ";
>>>> -  name[StatInt_pthread_cond_signal]      = "  pthread_cond_signal             ";
>>>> -  name[StatInt_pthread_cond_broadcast]   = "  pthread_cond_broadcast          ";
>>>> -  name[StatInt_pthread_cond_wait]        = "  pthread_cond_wait               ";
>>>> -  name[StatInt_pthread_cond_timedwait]   = "  pthread_cond_timedwait          ";
>>>> +  name[StatInt_pthread_cond_init_2_3_2]  = "  pthread_cond_init               ";
>>>> +  name[StatInt_pthread_cond_destroy_2_3_2]
>>>> +                                         = "  pthread_cond_destroy            ";
>>>> +  name[StatInt_pthread_cond_signal_2_3_2]= "  pthread_cond_signal             ";
>>>> +  name[StatInt_pthread_cond_broadcast_2_3_2]
>>>> +                                         = "  pthread_cond_broadcast          ";
>>>> +  name[StatInt_pthread_cond_wait_2_3_2]  = "  pthread_cond_wait               ";
>>>> +  name[StatInt_pthread_cond_timedwait_2_3_2]
>>>> +                                         = "  pthread_cond_timedwait          ";
>>>>    name[StatInt_pthread_barrier_init]     = "  pthread_barrier_init            ";
>>>>    name[StatInt_pthread_barrier_destroy]  = "  pthread_barrier_destroy         ";
>>>>    name[StatInt_pthread_barrier_wait]     = "  pthread_barrier_wait            ";
>>>>
>>>> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h
>>>> URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h?rev=189767&r1=189766&r2=189767&view=diff
>>>> ==============================================================================
>>>> --- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h (original)
>>>> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h Mon Sep  2 13:06:28 2013
>>>> @@ -164,12 +164,12 @@ enum StatType {
>>>>    StatInt_pthread_rwlock_trywrlock,
>>>>    StatInt_pthread_rwlock_timedwrlock,
>>>>    StatInt_pthread_rwlock_unlock,
>>>> -  StatInt_pthread_cond_init,
>>>> -  StatInt_pthread_cond_destroy,
>>>> -  StatInt_pthread_cond_signal,
>>>> -  StatInt_pthread_cond_broadcast,
>>>> -  StatInt_pthread_cond_wait,
>>>> -  StatInt_pthread_cond_timedwait,
>>>> +  StatInt_pthread_cond_init_2_3_2,
>>>> +  StatInt_pthread_cond_destroy_2_3_2,
>>>> +  StatInt_pthread_cond_signal_2_3_2,
>>>> +  StatInt_pthread_cond_broadcast_2_3_2,
>>>> +  StatInt_pthread_cond_wait_2_3_2,
>>>> +  StatInt_pthread_cond_timedwait_2_3_2,
>>>>    StatInt_pthread_barrier_init,
>>>>    StatInt_pthread_barrier_destroy,
>>>>    StatInt_pthread_barrier_wait,
>>>>
>>>>
>>>> _______________________________________________
>>>> llvm-commits mailing list
>>>> llvm-commits at cs.uiuc.edu
>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>>
>>>
>>>
>>> --
>>> Alexander Potapenko
>>> Software Engineer
>>> Google Moscow
>
>
>
> --
> Alexander Potapenko
> Software Engineer
> Google Moscow



More information about the llvm-commits mailing list