1*c7081b5bSDmitry Vyukov // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
2*c7081b5bSDmitry Vyukov 
3*c7081b5bSDmitry Vyukov // Use of gethostent provokes caching of some resources inside of libc.
4*c7081b5bSDmitry Vyukov // They are freed in __libc_thread_freeres very late in thread lifetime,
5*c7081b5bSDmitry Vyukov // after our ThreadFinish. __libc_thread_freeres calls free which
6*c7081b5bSDmitry Vyukov // previously crashed in malloc hooks.
7*c7081b5bSDmitry Vyukov 
8*c7081b5bSDmitry Vyukov #include "../test.h"
9*c7081b5bSDmitry Vyukov #include <netdb.h>
10*c7081b5bSDmitry Vyukov 
11*c7081b5bSDmitry Vyukov long X;
12*c7081b5bSDmitry Vyukov 
__sanitizer_malloc_hook(void * ptr,size_t size)13*c7081b5bSDmitry Vyukov extern "C" void __sanitizer_malloc_hook(void *ptr, size_t size) {
14*c7081b5bSDmitry Vyukov   __atomic_fetch_add(&X, 1, __ATOMIC_RELAXED);
15*c7081b5bSDmitry Vyukov }
16*c7081b5bSDmitry Vyukov 
__sanitizer_free_hook(void * ptr)17*c7081b5bSDmitry Vyukov extern "C" void __sanitizer_free_hook(void *ptr) {
18*c7081b5bSDmitry Vyukov   __atomic_fetch_sub(&X, 1, __ATOMIC_RELAXED);
19*c7081b5bSDmitry Vyukov }
20*c7081b5bSDmitry Vyukov 
Thread(void * x)21*c7081b5bSDmitry Vyukov void *Thread(void *x) {
22*c7081b5bSDmitry Vyukov   sethostent(1);
23*c7081b5bSDmitry Vyukov   gethostbyname("llvm.org");
24*c7081b5bSDmitry Vyukov   gethostent();
25*c7081b5bSDmitry Vyukov   endhostent();
26*c7081b5bSDmitry Vyukov   return NULL;
27*c7081b5bSDmitry Vyukov }
28*c7081b5bSDmitry Vyukov 
main()29*c7081b5bSDmitry Vyukov int main() {
30*c7081b5bSDmitry Vyukov   pthread_t th;
31*c7081b5bSDmitry Vyukov   pthread_create(&th, NULL, Thread, NULL);
32*c7081b5bSDmitry Vyukov   pthread_join(th, NULL);
33*c7081b5bSDmitry Vyukov   fprintf(stderr, "DONE\n");
34*c7081b5bSDmitry Vyukov   return 0;
35*c7081b5bSDmitry Vyukov }
36*c7081b5bSDmitry Vyukov 
37*c7081b5bSDmitry Vyukov // CHECK: DONE
38