diff --git a/repos/libports/lib/symbols/libc b/repos/libports/lib/symbols/libc index 39bfa2f733..e3de45d2d5 100644 --- a/repos/libports/lib/symbols/libc +++ b/repos/libports/lib/symbols/libc @@ -1294,6 +1294,7 @@ __cxa_guard_release T __cxa_init_primary_exception T __cxa_pure_virtual T __cxa_rethrow T +__cxa_thread_atexit T __cxa_throw T __cxa_throw_bad_array_length T __cxa_throw_bad_array_new_length T diff --git a/repos/libports/ports/libc.hash b/repos/libports/ports/libc.hash index a471669f14..f0b791929a 100644 --- a/repos/libports/ports/libc.hash +++ b/repos/libports/ports/libc.hash @@ -1 +1 @@ -b856473bd43dea76e963f35bdbdd1d49d2d70e6b +a4d148016cfbc4c494b277e164d67617cf540e31 diff --git a/repos/libports/src/lib/libc/patches/thread_local.patch b/repos/libports/src/lib/libc/patches/thread_local.patch index 89fa01b06b..f3356ff325 100644 --- a/repos/libports/src/lib/libc/patches/thread_local.patch +++ b/repos/libports/src/lib/libc/patches/thread_local.patch @@ -21,3 +21,23 @@ #endif /* __STDC_VERSION__ || __STDC_VERSION__ < 201112L */ /* +--- src/lib/libc/lib/libc/stdlib/cxa_thread_atexit_impl.c.orig 2022-08-16 17:53:26.334343226 +0200 ++++ src/lib/libc/lib/libc/stdlib/cxa_thread_atexit_impl.c 2022-08-17 13:37:34.445860493 +0200 +@@ -105,12 +105,17 @@ + { + struct dl_phdr_info phdr_info; + ++/* XXX this unload detection mechanism does not work on Genode */ ++#if 0 + if (_rtld_addr_phdr(dtor->dso, &phdr_info) && + __elf_phdr_match_addr(&phdr_info, dtor->func)) ++#endif + dtor->func(dtor->obj); ++#if 0 + else + fprintf(stderr, "__cxa_thread_call_dtors: dtr %p from " + "unloaded dso, skipping\n", (void *)(dtor->func)); ++#endif + } + + static void diff --git a/repos/libports/src/lib/libc/pthread.cc b/repos/libports/src/lib/libc/pthread.cc index 9619800dd7..8481dac372 100644 --- a/repos/libports/src/lib/libc/pthread.cc +++ b/repos/libports/src/lib/libc/pthread.cc @@ -685,8 +685,15 @@ extern "C" { } + /* implemented in libc contrib sources */ + void __cxa_thread_call_dtors(); + void pthread_exit(void *value_ptr) { + /* call 'thread_local' destructors */ + + __cxa_thread_call_dtors(); + /* call TLS key destructors */ bool at_least_one_destructor_called; diff --git a/repos/libports/src/test/pthread/main.cc b/repos/libports/src/test/pthread/main.cc index 4fce74233c..bf7a9e406c 100644 --- a/repos/libports/src/test/pthread/main.cc +++ b/repos/libports/src/test/pthread/main.cc @@ -1153,6 +1153,46 @@ static void test_tls() } +static bool thread_local_destructor_called = false; + + +struct Thread_local +{ + int x = 0; + + ~Thread_local() + { + thread_local_destructor_called = true; + } +}; + + +static thread_local Thread_local thread_local_var; + + +static void *thread_local_test_func(void *) +{ + /* must access the variable to have the destructor called */ + thread_local_var.x = 1; + return nullptr; +} + + +static void test_thread_local_destructor() +{ + pthread_t t; + void *retval; + + pthread_create(&t, 0, thread_local_test_func, nullptr); + pthread_join(t, &retval); + + if (!thread_local_destructor_called) { + Genode::error("thread_local destructor was not called"); + exit(-1); + } +} + + int main(int argc, char **argv) { printf("--- pthread test ---\n"); @@ -1171,6 +1211,7 @@ int main(int argc, char **argv) test_cond(); test_cleanup(); test_tls(); + test_thread_local_destructor(); printf("--- returning from main ---\n"); return 0;