Skip to content

thread specific key for __cxa_get_globals not destroyed on dlclose #60489

@k15tfu

Description

@k15tfu

Hi!

It turned out that a shared library with statically linked libc++.a and libc++abi.a leaks pthread_key_t handles when unloading by dlclose() and after a certain number of loading/unloading the PTHREAD_KEYS_MAX (or similar) limit is reached and we get cannot create thread specific key for __cxa_get_globals() error, here is demo app:

$ cat main.c
#include <dlfcn.h>
#include <stdio.h>

int main() {
    for (int i = 0; i < 10000; ++i) {
        void* library_handle = dlopen("/path/to/libsomelib.so", RTLD_LAZY | RTLD_LOCAL);
        printf("%d dlopen = %p\n", i, library_handle);

        dlclose(library_handle);
    }

    return 0;
}
$ cat somelib.cpp
#include <exception>
#include <stdexcept>

std::exception_ptr general_error = std::make_exception_ptr(std::runtime_error("General error"));

Build & run:

$ ./main
0 dlopen = 0x55ce993fd2a0
[...]
1022 dlopen = 0x55ce993fd2a0
1023 dlopen = 0x55ce993fd2a0
libc++abi: cannot create thread specific key for __cxa_get_globals()

Backtrace:

Process 26551 stopped
* thread #1, name = 'main', stop reason = signal SIGABRT
    frame #0: 0x00007ffff781ce87 libc.so.6`__GI_raise(sig=2) at raise.c:51
(lldb) bt
error: libdl.so.2 0x00012adf: adding range [0x12c0-0x12d8) which has a base that is less than the function's low PC 0x16e0. Please file a bug and attach the file at the start of this error message
error: libdl.so.2 0x00012adf: adding range [0x12dc-0x12e1) which has a base that is less than the function's low PC 0x16e0. Please file a bug and attach the file at the start of this error message
* thread #1, name = 'main', stop reason = signal SIGABRT
  * frame #0: 0x00007ffff781ce87 libc.so.6`__GI_raise(sig=2) at raise.c:51
    frame #1: 0x00007ffff781e7f1 libc.so.6`__GI_abort at abort.c:79
    frame #2: 0x00007ffff75aea06 libsomelib.so`abort_message + 198
    frame #3: 0x00007ffff75cf2d8 libsomelib.so`__cxxabiv1::(anonymous namespace)::construct_() + 40
    frame #4: 0x00007ffff738f907 libpthread.so.0`__pthread_once_slow + 183
    frame #5: 0x00007ffff75cf1f4 libsomelib.so`__cxa_get_globals + 20
    frame #6: 0x00007ffff75b0467 libsomelib.so`__cxa_throw + 23
    frame #7: 0x00007ffff75ae01c libsomelib.so`std::exception_ptr std::make_exception_ptr<std::runtime_error>(std::runtime_error) + 76
    frame #8: 0x00007ffff75adec8 libsomelib.so`__cxx_global_var_init + 40
    frame #9: 0x00007ffff75adf09 libsomelib.so`_GLOBAL__sub_I_somelib.cpp + 9
    frame #10: 0x00007ffff7de38d3 ld-linux-x86-64.so.2`___lldb_unnamed_symbol50$$ld-linux-x86-64.so.2 + 259
    frame #11: 0x00007ffff7de839f ld-linux-x86-64.so.2`___lldb_unnamed_symbol81$$ld-linux-x86-64.so.2 + 1087
    frame #12: 0x00007ffff794516f libc.so.6`__GI__dl_catch_exception(exception=0x00007fffffffe610, operate=(ld-linux-x86-64.so.2`___lldb_unnamed_symbol81$$ld-linux-x86-64.so.2), args=0x00007fffffffe630) at dl-error-skeleton.c:196
    frame #13: 0x00007ffff7de796a ld-linux-x86-64.so.2`___lldb_unnamed_symbol79$$ld-linux-x86-64.so.2 + 186
    frame #14: 0x00007ffff7bcff96 libdl.so.2`dlopen_doit(a=0x00007fffffffe860) at dlopen.c:66
    frame #15: 0x00007ffff794516f libc.so.6`__GI__dl_catch_exception(exception=0x00007fffffffe800, operate=(libdl.so.2`dlopen_doit at dlopen.c:58), args=0x00007fffffffe860) at dl-error-skeleton.c:196
    frame #16: 0x00007ffff79451ff libc.so.6`__GI__dl_catch_error(objname=0x00007ffff7dd20f0, errstring=0x00007ffff7dd20f8, mallocedp=0x00007ffff7dd20e8, operate=<unavailable>, args=<unavailable>) at dl-error-skeleton.c:215
    frame #17: 0x00007ffff7bd0745 libdl.so.2`_dlerror_run(operate=(libdl.so.2`dlopen_doit at dlopen.c:58), args=0x00007fffffffe860) at dlerror.c:162
    frame #18: 0x00007ffff7bd0051 libdl.so.2`__dlopen at dlopen.c:87
    frame #19: 0x00007ffff7bd0030 libdl.so.2`__dlopen(file=<unavailable>, mode=<unavailable>)
    frame #20: 0x000055555555471c main`main + 34
    frame #21: 0x00007ffff77ffc87 libc.so.6`__libc_start_main(main=(main`main), argc=1, argv=0x00007fffffffe998, init=<unavailable>, fini=<unavailable>, rtld_fini=<unavailable>, stack_end=0x00007fffffffe988) at libc-start.c:310
    frame #22: 0x000055555555461a main`_start + 42

Clang 12.0.0
Linux x64

Metadata

Metadata

Assignees

No one assigned

    Labels

    libc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.libc++abilibc++abi C++ Runtime Library. Not libc++.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions