Merge "linker_main: acquire loader lock earlier and release it later" into main
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index e92aada..8a20670 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -44,7 +44,6 @@
#include "linker_utils.h"
#include "private/KernelArgumentBlock.h"
-#include "private/ScopedPthreadMutexLocker.h"
#include "private/bionic_call_ifunc_resolver.h"
#include "private/bionic_globals.h"
#include "private/bionic_tls.h"
@@ -499,11 +498,6 @@
if (!get_cfi_shadow()->InitialLinkDone(solist)) __linker_cannot_link(g_argv[0]);
- // A constructor could spawn a thread that calls into the loader, so as soon
- // as we've called a constructor, we need to hold the lock while accessing
- // global loader state.
- ScopedPthreadMutexLocker locker(&g_dl_mutex);
-
si->call_pre_init_constructors();
si->call_constructors();
@@ -696,6 +690,13 @@
* function, or other GOT reference will generate a segfault.
*/
extern "C" ElfW(Addr) __linker_init(void* raw_args) {
+ // Unlock the loader mutex immediately before transferring to the executable's
+ // entry point. This must happen after destructors are called in this function
+ // (e.g. ~soinfo), so declare this variable very early.
+ struct DlMutexUnlocker {
+ ~DlMutexUnlocker() { pthread_mutex_unlock(&g_dl_mutex); }
+ } unlocker;
+
// Initialize TLS early so system calls and errno work.
KernelArgumentBlock args(raw_args);
bionic_tcb temp_tcb __attribute__((uninitialized));
@@ -758,6 +759,11 @@
// Initialize the linker's static libc's globals
__libc_init_globals();
+ // A constructor could spawn a thread that calls into the loader, so as soon
+ // as we've called a constructor, we need to hold the lock until transferring
+ // to the entry point.
+ pthread_mutex_lock(&g_dl_mutex);
+
// Initialize the linker's own global variables
tmp_linker_so.call_constructors();