Skip to content

Commit 3498e6e

Browse files
committed
Ensure static TLS region is free'd last
We were using `__cxa_thread_atexit` to register the funtion for free'ing TLS data. And because were were running the exit handlers `__pthread_exit_run_handlers` before `__pthread_tsd_run_dtors` it meant that any pthread_key descructor functions would not be able to access TLS variables. Instead we really need to delay free'ing of TLS data until all exit handlers and pthread_key descructors have been run. This was causing failure of `lsan.test_stdio_locking` due to the fact that lsan uses TLS during pthread key destruction. Specifically `thread_finalize` (a pthread_key desctructor function) calls `ThreadFinish` which in turn calls `GetCurrentThread` which uses a thread local variable to store the current thread ID. This change should allow #14489 to be dramatically simplified because it will allow the use of TLS variables to implement the atexit queue.
1 parent 939427a commit 3498e6e

11 files changed

+27
-20
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ jobs:
369369
steps:
370370
- run-tests:
371371
# also add a few asan tests
372-
test_targets: "wasm2 asan.test_embind* asan.test_abort_on_exceptions asan.test_ubsan_full_left_shift_fsanitize_integer asan.test_pthread* asan.test_dyncall_specific_minimal_runtime asan.test_async_hello"
372+
test_targets: "wasm2 asan.test_embind* asan.test_abort_on_exceptions asan.test_ubsan_full_left_shift_fsanitize_integer asan.test_pthread* asan.test_dyncall_specific_minimal_runtime asan.test_async_hello lsan.test_stdio_locking"
373373
test-wasm3:
374374
executor: bionic
375375
steps:

system/lib/compiler-rt/lib/lsan/lsan_interceptors.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,15 +562,14 @@ void InitializeInterceptors() {
562562
LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK;
563563

564564
LSAN_MAYBE_INTERCEPT_STRERROR;
565+
#endif // !SANITIZER_FUCHSIA && !SANITIZER_EMSCRIPTEN
565566

566567
#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD
567568
if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
568569
Report("LeakSanitizer: failed to create thread key.\n");
569570
Die();
570571
}
571572
#endif
572-
573-
#endif // !SANITIZER_FUCHSIA
574573
}
575574

576575
} // namespace __lsan

system/lib/libc/musl/src/thread/pthread_key_create.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,7 @@ int __pthread_key_delete(pthread_key_t k)
3939
return 0;
4040
}
4141

42-
#ifdef __EMSCRIPTEN__
43-
void EMSCRIPTEN_KEEPALIVE __pthread_tsd_run_dtors()
44-
#else
4542
void __pthread_tsd_run_dtors()
46-
#endif
4743
{
4844
pthread_t self = __pthread_self();
4945
int i, j, not_finished = self->tsd_used;

system/lib/pthread/emscripten_thread_state.s

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
.globaltype __tls_base, i32
2+
13
.globaltype thread_id, i32
24
thread_id:
35

@@ -24,6 +26,14 @@ _emscripten_thread_init:
2426
global.set is_runtime_thread
2527
end_function
2628

29+
# Accessor for `__tls_base` symbol which is a wasm global an not directly
30+
# accessible from C/C++.
31+
.globl _emscripten_tls_base
32+
_emscripten_tls_base:
33+
.functype _emscripten_tls_base () -> (i32)
34+
global.get __tls_base
35+
end_function
36+
2737
# Semantically the same as testing "!ENVIRONMENT_IS_PTHREAD" in JS
2838
.globl emscripten_is_main_runtime_thread
2939
emscripten_is_main_runtime_thread:

system/lib/pthread/emscripten_tls_init.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,6 @@ extern int __cxa_thread_atexit(void (*)(void *), void *, void *);
2121

2222
extern int __dso_handle;
2323

24-
static void free_tls(void* tls_block) {
25-
#ifdef DEBUG_TLS
26-
printf("tls free: thread[%p] dso[%p] <- %p\n", pthread_self(), &__dso_handle, tls_block);
27-
#endif
28-
emscripten_builtin_free(tls_block);
29-
}
30-
3124
void* emscripten_tls_init(void) {
3225
size_t tls_size = __builtin_wasm_tls_size();
3326
size_t tls_align = __builtin_wasm_tls_align();
@@ -39,6 +32,5 @@ void* emscripten_tls_init(void) {
3932
printf("tls init: thread[%p] dso[%p] -> %p\n", pthread_self(), &__dso_handle, tls_block);
4033
#endif
4134
__wasm_init_tls(tls_block);
42-
__cxa_thread_atexit(free_tls, tls_block, &__dso_handle);
4335
return tls_block;
4436
}

system/lib/pthread/pthread_create.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ extern int __pthread_create_js(struct pthread *thread, const pthread_attr_t *att
2222
extern void _emscripten_thread_init(int, int, int);
2323
extern void __pthread_exit_run_handlers();
2424
extern void __pthread_detached_exit();
25+
extern void* _emscripten_tls_base();
2526
extern int8_t __dso_handle;
2627

2728
static void dummy_0()
@@ -104,6 +105,16 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
104105
return __pthread_create_js(new, attrp, entry, arg);
105106
}
106107

108+
static void free_tls_data() {
109+
void* tls_block = _emscripten_tls_base();
110+
if (tls_block) {
111+
#ifdef DEBUG_TLS
112+
printf("tls free: thread[%p] dso[%p] <- %p\n", pthread_self(), &__dso_handle, tls_block);
113+
#endif
114+
emscripten_builtin_free(tls_block);
115+
}
116+
}
117+
107118
void _emscripten_thread_exit(void* result) {
108119
struct pthread *self = __pthread_self();
109120
assert(self);
@@ -117,6 +128,8 @@ void _emscripten_thread_exit(void* result) {
117128
// Call into the musl function that runs destructors of all thread-specific data.
118129
__pthread_tsd_run_dtors();
119130

131+
free_tls_data();
132+
120133
__lock(self->exitlock);
121134

122135
if (self == emscripten_main_browser_thread_id()) {

tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.exports

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ M
1414
N
1515
O
1616
P
17-
Q
17+
v
1818
w
1919
x
2020
y

tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.funcs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ $emscripten_stack_set_limits
3636
$emscripten_sync_run_in_main_thread
3737
$emscripten_sync_run_in_main_thread
3838
$emscripten_tls_init
39-
$free_tls
4039
$init_file_lock
4140
$init_mparams
4241
$main

tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.imports

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,3 @@ a.r
1919
a.s
2020
a.t
2121
a.u
22-
a.v

tests/other/metadce/minimal_main_Oz_USE_PTHREADS_PROXY_TO_PTHREAD.sent

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,3 @@ r
1919
s
2020
t
2121
u
22-
v
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
16977
1+
16962

0 commit comments

Comments
 (0)