libc: support 'thread_local' variable destructors

Fixes #4585
This commit is contained in:
Christian Prochaska 2022-08-17 14:16:47 +02:00 committed by Christian Helmuth
parent 42edac8a34
commit fb454a28fe
5 changed files with 70 additions and 1 deletions

View File

@ -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

View File

@ -1 +1 @@
b856473bd43dea76e963f35bdbdd1d49d2d70e6b
a4d148016cfbc4c494b277e164d67617cf540e31

View File

@ -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

View File

@ -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;

View File

@ -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;