Skip to content

Commit 999313d

Browse files
authored
[sanitizer] Switch from lazy ThreadDescriptorSize (#108923)
`ThreadDescriptorSize` uses `dlsym` which may use malloc in unexpected time. It's relatively easy to init size from the main init.
1 parent c86b1b0 commit 999313d

File tree

2 files changed

+17
-15
lines changed

2 files changed

+17
-15
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ static void GetGLibcVersion(int *major, int *minor, int *patch) {
224224
// to get the pointer to thread-specific data keys in the thread control block.
225225
# if (SANITIZER_FREEBSD || SANITIZER_GLIBC) && !SANITIZER_GO
226226
// sizeof(struct pthread) from glibc.
227-
static atomic_uintptr_t thread_descriptor_size;
227+
static uptr thread_descriptor_size;
228228

229229
// FIXME: Implementation is very GLIBC specific, but it's used by FREEBSD.
230230
static uptr ThreadDescriptorSizeFallback() {
@@ -305,20 +305,7 @@ static uptr ThreadDescriptorSizeFallback() {
305305
# endif
306306
}
307307

308-
uptr ThreadDescriptorSize() {
309-
uptr val = atomic_load_relaxed(&thread_descriptor_size);
310-
if (val)
311-
return val;
312-
// _thread_db_sizeof_pthread is a GLIBC_PRIVATE symbol that is exported in
313-
// glibc 2.34 and later.
314-
if (unsigned *psizeof = static_cast<unsigned *>(
315-
dlsym(RTLD_DEFAULT, "_thread_db_sizeof_pthread")))
316-
val = *psizeof;
317-
if (!val)
318-
val = ThreadDescriptorSizeFallback();
319-
atomic_store_relaxed(&thread_descriptor_size, val);
320-
return val;
321-
}
308+
uptr ThreadDescriptorSize() { return thread_descriptor_size; }
322309

323310
# if SANITIZER_GLIBC
324311
__attribute__((unused)) static size_t g_tls_size;
@@ -330,6 +317,15 @@ void InitTlsSize() {
330317
GetGLibcVersion(&major, &minor, &patch);
331318
g_use_dlpi_tls_data = major == 2 && minor >= 25;
332319

320+
if (major == 2 && minor >= 34) {
321+
// _thread_db_sizeof_pthread is a GLIBC_PRIVATE symbol that is exported in
322+
// glibc 2.34 and later.
323+
if (unsigned *psizeof = static_cast<unsigned *>(
324+
dlsym(RTLD_DEFAULT, "_thread_db_sizeof_pthread"))) {
325+
thread_descriptor_size = *psizeof;
326+
}
327+
}
328+
333329
# if defined(__aarch64__) || defined(__x86_64__) || \
334330
defined(__powerpc64__) || defined(__loongarch__)
335331
auto *get_tls_static_info = (void (*)(size_t *, size_t *))dlsym(
@@ -339,7 +335,11 @@ void InitTlsSize() {
339335
if (get_tls_static_info)
340336
get_tls_static_info(&g_tls_size, &tls_align);
341337
# endif
338+
342339
# endif // SANITIZER_GLIBC
340+
341+
if (!thread_descriptor_size)
342+
thread_descriptor_size = ThreadDescriptorSizeFallback();
343343
}
344344

345345
# if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64 || \

compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ TEST(SanitizerLinux, ThreadDescriptorSize) {
202202
void *result;
203203
ASSERT_EQ(0, pthread_create(&tid, 0, thread_descriptor_size_test_func, 0));
204204
ASSERT_EQ(0, pthread_join(tid, &result));
205+
EXPECT_EQ(0u, ThreadDescriptorSize());
206+
InitTlsSize();
205207
EXPECT_EQ((uptr)result, ThreadDescriptorSize());
206208
}
207209
# endif

0 commit comments

Comments
 (0)