mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Call thread finalizers on exit()
While we don't call POSIX thread key destructors from exit(), we do need to call these, since C++ uses it for TLS object destructors. See #1076
This commit is contained in:
parent
07db3004d6
commit
81ce2e4cbc
5 changed files with 56 additions and 22 deletions
|
@ -17,6 +17,7 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/cxxabi.h"
|
#include "libc/cxxabi.h"
|
||||||
|
#include "libc/intrin/cxaatexit.internal.h"
|
||||||
#include "libc/intrin/strace.internal.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/intrin/weaken.h"
|
#include "libc/intrin/weaken.h"
|
||||||
#include "libc/runtime/internal.h"
|
#include "libc/runtime/internal.h"
|
||||||
|
@ -36,13 +37,24 @@
|
||||||
* @noreturn
|
* @noreturn
|
||||||
*/
|
*/
|
||||||
wontreturn void exit(int exitcode) {
|
wontreturn void exit(int exitcode) {
|
||||||
const uintptr_t *p;
|
|
||||||
STRACE("exit(%d)", exitcode);
|
STRACE("exit(%d)", exitcode);
|
||||||
|
|
||||||
|
// call thread local c++ object destructors
|
||||||
|
if (_weaken(__cxa_thread_finalize)) {
|
||||||
|
_weaken(__cxa_thread_finalize)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// call atexit() and __cxa_atexit() destructors
|
||||||
if (_weaken(__cxa_finalize)) {
|
if (_weaken(__cxa_finalize)) {
|
||||||
_weaken(__cxa_finalize)(NULL);
|
_weaken(__cxa_finalize)(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// call __destructor__ and finiarray destructors
|
||||||
|
const uintptr_t *p;
|
||||||
for (p = __fini_array_end; p > __fini_array_start;) {
|
for (p = __fini_array_end; p > __fini_array_start;) {
|
||||||
((void (*)(void))(*--p))();
|
((void (*)(void))(*--p))();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// terminate process
|
||||||
_Exit(exitcode);
|
_Exit(exitcode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,24 +3,30 @@
|
||||||
|
|
||||||
PKGS += TEST_LIBC_THREAD
|
PKGS += TEST_LIBC_THREAD
|
||||||
|
|
||||||
TEST_LIBC_THREAD_SRCS := $(wildcard test/libc/thread/*.c)
|
TEST_LIBC_THREAD_FILES := $(wildcard test/libc/thread/*)
|
||||||
TEST_LIBC_THREAD_SRCS_TEST = $(filter %_test.c,$(TEST_LIBC_THREAD_SRCS))
|
TEST_LIBC_THREAD_SRCS_C = $(filter %_test.c,$(TEST_LIBC_THREAD_FILES))
|
||||||
|
TEST_LIBC_THREAD_SRCS_CC = $(filter %_test.cc,$(TEST_LIBC_THREAD_FILES))
|
||||||
|
|
||||||
|
TEST_LIBC_THREAD_SRCS = \
|
||||||
|
$(TEST_LIBC_THREAD_SRCS_C) \
|
||||||
|
$(TEST_LIBC_THREAD_SRCS_CC)
|
||||||
|
|
||||||
TEST_LIBC_THREAD_OBJS = \
|
TEST_LIBC_THREAD_OBJS = \
|
||||||
$(TEST_LIBC_THREAD_SRCS:%.c=o/$(MODE)/%.o)
|
$(TEST_LIBC_THREAD_SRCS_C:%.c=o/$(MODE)/%.o) \
|
||||||
|
$(TEST_LIBC_THREAD_SRCS_CC:%.cc=o/$(MODE)/%.o)
|
||||||
|
|
||||||
TEST_LIBC_THREAD_COMS = \
|
TEST_LIBC_THREAD_COMS = \
|
||||||
$(TEST_LIBC_THREAD_SRCS:%.c=o/$(MODE)/%.com)
|
$(TEST_LIBC_THREAD_OBJS:%.o=%.com)
|
||||||
|
|
||||||
TEST_LIBC_THREAD_BINS = \
|
TEST_LIBC_THREAD_BINS = \
|
||||||
$(TEST_LIBC_THREAD_COMS) \
|
$(TEST_LIBC_THREAD_COMS) \
|
||||||
$(TEST_LIBC_THREAD_COMS:%=%.dbg)
|
$(TEST_LIBC_THREAD_COMS:%=%.dbg)
|
||||||
|
|
||||||
TEST_LIBC_THREAD_TESTS = \
|
TEST_LIBC_THREAD_TESTS = \
|
||||||
$(TEST_LIBC_THREAD_SRCS_TEST:%.c=o/$(MODE)/%.com.ok)
|
$(TEST_LIBC_THREAD_OBJS:%.o=%.com.ok)
|
||||||
|
|
||||||
TEST_LIBC_THREAD_CHECKS = \
|
TEST_LIBC_THREAD_CHECKS = \
|
||||||
$(TEST_LIBC_THREAD_SRCS_TEST:%.c=o/$(MODE)/%.com.runs)
|
$(TEST_LIBC_THREAD_OBJS:%.o=%.com.runs)
|
||||||
|
|
||||||
TEST_LIBC_THREAD_DIRECTDEPS = \
|
TEST_LIBC_THREAD_DIRECTDEPS = \
|
||||||
LIBC_CALLS \
|
LIBC_CALLS \
|
||||||
|
@ -61,10 +67,6 @@ o/$(MODE)/test/libc/thread/%.com.dbg: \
|
||||||
$(APE_NO_MODIFY_SELF)
|
$(APE_NO_MODIFY_SELF)
|
||||||
@$(APELINK)
|
@$(APELINK)
|
||||||
|
|
||||||
o/$(MODE)/test/libc/thread/pthread_create_test.o: \
|
|
||||||
private CPPFLAGS += \
|
|
||||||
-DSTACK_FRAME_UNLIMITED
|
|
||||||
|
|
||||||
o/$(MODE)/test/libc/thread/pthread_kill_test.com.runs: \
|
o/$(MODE)/test/libc/thread/pthread_kill_test.com.runs: \
|
||||||
private .PLEDGE = stdio rpath wpath cpath fattr proc inet
|
private .PLEDGE = stdio rpath wpath cpath fattr proc inet
|
||||||
|
|
||||||
|
|
|
@ -73,13 +73,6 @@ void OnMainThreadExit(void *arg) {
|
||||||
_Exit((long)arg);
|
_Exit((long)arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(__cxa_thread_atexit, exit_wontInvokeThreadDestructors) {
|
|
||||||
SPAWN(fork);
|
|
||||||
__cxa_thread_atexit(OnMainThreadExit, (void *)123L, 0);
|
|
||||||
exit(0);
|
|
||||||
EXITS(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(__cxa_thread_atexit, pthread_exit_willInvokeThreadDestructors) {
|
TEST(__cxa_thread_atexit, pthread_exit_willInvokeThreadDestructors) {
|
||||||
SPAWN(fork);
|
SPAWN(fork);
|
||||||
__cxa_thread_atexit(OnMainThreadExit, (void *)123L, 0);
|
__cxa_thread_atexit(OnMainThreadExit, (void *)123L, 0);
|
||||||
|
|
30
test/libc/thread/tls_dtor_test.cc
Normal file
30
test/libc/thread/tls_dtor_test.cc
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*-*-mode:c++;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8-*-│
|
||||||
|
│ vi: set et ft=c++ ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2024 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
~Foo() {
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
thread_local Foo foo;
|
||||||
|
exit(1);
|
||||||
|
}
|
5
third_party/libcxxabi/test/BUILD.mk
vendored
5
third_party/libcxxabi/test/BUILD.mk
vendored
|
@ -52,6 +52,7 @@ THIRD_PARTY_LIBCXXABI_TEST_SRCS = \
|
||||||
third_party/libcxxabi/test/test_guard.pass.cc \
|
third_party/libcxxabi/test/test_guard.pass.cc \
|
||||||
third_party/libcxxabi/test/test_vector1.pass.cc \
|
third_party/libcxxabi/test/test_vector1.pass.cc \
|
||||||
third_party/libcxxabi/test/test_vector2.pass.cc \
|
third_party/libcxxabi/test/test_vector2.pass.cc \
|
||||||
|
third_party/libcxxabi/test/thread_local_destruction_order.pass.cc \
|
||||||
third_party/libcxxabi/test/test_vector3.pass.cc \
|
third_party/libcxxabi/test/test_vector3.pass.cc \
|
||||||
third_party/libcxxabi/test/uncaught_exception.pass.cc \
|
third_party/libcxxabi/test/uncaught_exception.pass.cc \
|
||||||
third_party/libcxxabi/test/uncaught_exceptions.pass.cc \
|
third_party/libcxxabi/test/uncaught_exceptions.pass.cc \
|
||||||
|
@ -67,10 +68,6 @@ THIRD_PARTY_LIBCXXABI_TEST_SRCS = \
|
||||||
THIRD_PARTY_LIBCXXABI_TEST_SRCS_TOOSLOW_COSMO = \
|
THIRD_PARTY_LIBCXXABI_TEST_SRCS_TOOSLOW_COSMO = \
|
||||||
third_party/libcxxabi/test/guard_threaded_test.pass.cc \
|
third_party/libcxxabi/test/guard_threaded_test.pass.cc \
|
||||||
|
|
||||||
# TODO: Add this test when #1073 is fixed
|
|
||||||
THIRD_PARTY_LIBCXXABI_TEST_SRCS_FAILING_COSMO = \
|
|
||||||
third_party/libcxxabi/test/thread_local_destruction_order.pass.cc
|
|
||||||
|
|
||||||
THIRD_PARTY_LIBCXXABI_TEST_SRCS_FAILING_GCC = \
|
THIRD_PARTY_LIBCXXABI_TEST_SRCS_FAILING_GCC = \
|
||||||
third_party/libcxxabi/test/catch_array_01.pass.cc \
|
third_party/libcxxabi/test/catch_array_01.pass.cc \
|
||||||
third_party/libcxxabi/test/catch_function_01.pass.cc \
|
third_party/libcxxabi/test/catch_function_01.pass.cc \
|
||||||
|
|
Loading…
Reference in a new issue