Improve pthread_create failure handling.
Return EAGAIN rather than aborting if we fail to set up the TLS for a new
thread.
Add a test that uses all the VMAs so we can properly test these edge cases.
Add an explicit test for pthread_attr_setdetachstate, which we use in the
previous test, but other than that has no tests.
Remove support for ro.logd.timestamp/persist.logd.timestamp, which doesn't
seem to be used, and which prevents us from logging failures in cases where
mmap fails (because we need to mmap in the system property implementation).
Bug: http://b/65608572
Test: ran tests
Change-Id: I9009f06546e1c2cc55eff996d08b55eff3482343
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 09ae16c..65ab92c 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -50,7 +50,7 @@
#endif
// This code is used both by each new pthread and the code that initializes the main thread.
-void __init_tls(pthread_internal_t* thread) {
+bool __init_tls(pthread_internal_t* thread) {
// Slot 0 must point to itself. The x86 Linux kernel reads the TLS from %fs:0.
thread->tls[TLS_SLOT_SELF] = thread->tls;
thread->tls[TLS_SLOT_THREAD_ID] = thread;
@@ -59,16 +59,25 @@
size_t allocation_size = BIONIC_TLS_SIZE + (2 * PTHREAD_GUARD_SIZE);
void* allocation = mmap(nullptr, allocation_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (allocation == MAP_FAILED) {
- async_safe_fatal("failed to allocate TLS: %s", strerror(errno));
+ async_safe_format_log(ANDROID_LOG_WARN, "libc",
+ "pthread_create failed: couldn't allocate TLS: %s", strerror(errno));
+ return false;
}
+
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, allocation, allocation_size, "bionic TLS guard");
+ // Carve out the writable TLS section.
thread->bionic_tls = reinterpret_cast<bionic_tls*>(static_cast<char*>(allocation) +
PTHREAD_GUARD_SIZE);
if (mprotect(thread->bionic_tls, BIONIC_TLS_SIZE, PROT_READ | PROT_WRITE) != 0) {
- async_safe_fatal("failed to mprotect TLS: %s", strerror(errno));
+ async_safe_format_log(ANDROID_LOG_WARN, "libc",
+ "pthread_create failed: couldn't mprotect TLS: %s", strerror(errno));
+ munmap(allocation, allocation_size);
+ return false;
}
+
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, thread->bionic_tls, BIONIC_TLS_SIZE, "bionic TLS");
+ return true;
}
void __init_thread_stack_guard(pthread_internal_t* thread) {
@@ -194,7 +203,10 @@
thread->mmap_size = mmap_size;
thread->attr = *attr;
- __init_tls(thread);
+ if (!__init_tls(thread)) {
+ if (thread->mmap_size != 0) munmap(thread->attr.stack_base, thread->mmap_size);
+ return EAGAIN;
+ }
__init_thread_stack_guard(thread);
*threadp = thread;