Skip to content

Commit c7081b5

Browse files
committed
tsan: fix crash during thread exit
Use of gethostent provokes caching of some resources inside of libc. They are freed in __libc_thread_freeres very late in thread lifetime, after our ThreadFinish. __libc_thread_freeres calls free which previously crashed in malloc hooks. Fix it by setting ignore_interceptors for finished threads, which in turn prevents malloc hooks. Reviewed By: melver Differential Revision: https://reviews.llvm.org/D113989
1 parent 50acc6d commit c7081b5

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,9 @@ void ThreadFinish(ThreadState *thr) {
228228
DontNeedShadowFor(thr->tls_addr, thr->tls_size);
229229
thr->is_dead = true;
230230
thr->is_inited = false;
231+
#if !SANITIZER_GO
232+
thr->ignore_interceptors++;
233+
#endif
231234
ctx->thread_registry.FinishThread(thr->tid);
232235
}
233236

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

0 commit comments

Comments
 (0)