[PATCH 3/8] elf: Avoid redundant ld.so.cache reload after first load
Adhemerval Zanella
adhemerval.zanella@linaro.org
Mon Jul 6 21:14:39 GMT 2026
_dl_check_ldsocache_needs_loading only stored the stat fields it
compares (mtime, ino, size, dev) on the path where a cache was already
loaded. On the very first call CACHE is NULL and the function returned
"needs loading" without recording those fields, leaving
new_cache_file_time zero. The next call then copied that zero value
into cache_file_time and compared it against the freshly stat'd values,
which always differed, forcing a second, unnecessary load (munmap +
mmap + re-parse) of an unchanged cache at every startup.
It can be shown with repro:
$ cat << EOF > repro.c
#include <dlfcn.h>
int main (void) { dlopen ("does-not-exist-xyz.so.99", RTLD_NOW); return 0; }
EOF
$ gcc repro.c -o repro
$ strace -f -e trace=openat elf/ld.so --library-path . ./repro 2>&1 | grep -c "/etc/ld.so.cache"
The result should be 1, instead of 2.
Record the stat fields as soon as the stat succeeds, before the
CACHE == NULL early return, so the following call has an accurate
baseline and does not spuriously reload.
---
elf/dl-cache.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/elf/dl-cache.c b/elf/dl-cache.c
index 498196d0aa3..03bcd5bd06e 100644
--- a/elf/dl-cache.c
+++ b/elf/dl-cache.c
@@ -433,17 +433,20 @@ _dl_check_ldsocache_needs_loading (void)
if (rv < 0)
return false;
- /* Any file is better than no file (likely the first time
- through). */
- if (cache == NULL)
- return true;
-
- /* Store the fields we check, in order they're likely to differ. */
+ /* Store the fields we check, in order they're likely to differ. We
+ must do this even for the first load (CACHE == NULL below), so that
+ the next call copies an accurate NEW_CACHE_FILE_TIME into
+ CACHE_FILE_TIME and does not spuriously reload the unchanged cache. */
new_cache_file_time.mtime = new_cache_file_stat.st_mtime;
new_cache_file_time.ino = new_cache_file_stat.st_ino;
new_cache_file_time.size = new_cache_file_stat.st_size;
new_cache_file_time.dev = new_cache_file_stat.st_dev;
+ /* Any file is better than no file (likely the first time
+ through). */
+ if (cache == NULL)
+ return true;
+
/* At this point, NEW_CACHE_FILE_TIME is valid as well as
CACHE_FILE_TIME, so we compare them. */
return (memcmp (&new_cache_file_time, &cache_file_time,
--
2.43.0
More information about the Libc-alpha
mailing list