Skip to content

Commit 30295d0

Browse files
[libc] add an defense for reentrant exit
1 parent c443d6a commit 30295d0

File tree

5 files changed

+41
-3
lines changed

5 files changed

+41
-3
lines changed

libc/src/__support/threads/thread.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ ThreadAtExitCallbackMgr *get_thread_atexit_callback_mgr() {
154154
}
155155

156156
void call_atexit_callbacks(ThreadAttributes *attrib) {
157+
if (attrib->dtors_called)
158+
return;
159+
attrib->dtors_called = true;
157160
attrib->atexit_callback_mgr->call();
158161
for (size_t i = 0; i < TSS_KEY_COUNT; ++i) {
159162
TSSValueUnit &unit = tss_values[i];

libc/src/__support/threads/thread.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,14 @@ struct alignas(STACK_ALIGNMENT) ThreadAttributes {
109109
ThreadReturnValue retval;
110110
ThreadAtExitCallbackMgr *atexit_callback_mgr;
111111
void *platform_data;
112+
bool dtors_called;
112113

113-
constexpr ThreadAttributes()
114+
LIBC_INLINE constexpr ThreadAttributes()
114115
: detach_state(uint32_t(DetachState::DETACHED)), stack(nullptr),
115116
stacksize(0), guardsize(0), tls(0), tls_size(0), owned_stack(false),
116117
tid(-1), style(ThreadStyle::POSIX), retval(),
117-
atexit_callback_mgr(nullptr), platform_data(nullptr) {}
118+
atexit_callback_mgr(nullptr), platform_data(nullptr),
119+
dtors_called(false) {}
118120
};
119121

120122
using TSSDtor = void(void *);

libc/test/integration/src/__support/threads/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,14 @@ add_integration_test(
3535
DEPENDS
3636
libc.src.__support.threads.thread
3737
)
38+
39+
add_integration_test(
40+
double_exit_test
41+
SUITE
42+
libc-support-threads-integration-tests
43+
SRCS
44+
double_exit_test.cpp
45+
DEPENDS
46+
libc.src.__support.threads.thread
47+
libc.src.stdlib.exit
48+
)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===-- Test handling of thread local data --------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/__support/threads/thread.h"
10+
#include "src/stdlib/exit.h"
11+
#include "test/IntegrationTest/test.h"
12+
13+
extern "C" {
14+
[[gnu::weak]]
15+
void *__dso_handle = nullptr;
16+
int __cxa_thread_atexit_impl(void (*func)(void *), void *arg, void *dso);
17+
}
18+
19+
TEST_MAIN() {
20+
__cxa_thread_atexit_impl([](void *) { LIBC_NAMESPACE::exit(0); }, nullptr,
21+
__dso_handle);
22+
return 0;
23+
}

libc/test/integration/src/__support/threads/main_exit_test.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ bool called = false;
1414
extern "C" {
1515
[[gnu::weak]]
1616
void *__dso_handle = nullptr;
17-
1817
int __cxa_thread_atexit_impl(void (*func)(void *), void *arg, void *dso);
1918
}
2019

0 commit comments

Comments
 (0)