Home | History | Annotate | Download | only in src
      1 //===----------------------- cxa_thread_atexit.cpp ------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is dual licensed under the MIT and the University of Illinois Open
      6 // Source Licenses. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "abort_message.h"
     11 #include "cxxabi.h"
     12 #include <__threading_support>
     13 #include <cstdlib>
     14 
     15 namespace __cxxabiv1 {
     16 
     17   using Dtor = void(*)(void*);
     18 
     19   extern "C"
     20 #ifndef HAVE___CXA_THREAD_ATEXIT_IMPL
     21   // A weak symbol is used to detect this function's presence in the C library
     22   // at runtime, even if libc++ is built against an older libc
     23   _LIBCXXABI_WEAK
     24 #endif
     25   int __cxa_thread_atexit_impl(Dtor, void*, void*);
     26 
     27 #ifndef HAVE___CXA_THREAD_ATEXIT_IMPL
     28 
     29 namespace {
     30   // This implementation is used if the C library does not provide
     31   // __cxa_thread_atexit_impl() for us.  It has a number of limitations that are
     32   // difficult to impossible to address without ..._impl():
     33   //
     34   // - dso_symbol is ignored.  This means that a shared library may be unloaded
     35   //   (via dlclose()) before its thread_local destructors have run.
     36   //
     37   // - thread_local destructors for the main thread are run by the destructor of
     38   //   a static object.  This is later than expected; they should run before the
     39   //   destructors of any objects with static storage duration.
     40   //
     41   // - thread_local destructors on non-main threads run on the first iteration
     42   //   through the __libccpp_tls_key destructors.
     43   //   std::notify_all_at_thread_exit() and similar functions must be careful to
     44   //   wait until the second iteration to provide their intended ordering
     45   //   guarantees.
     46   //
     47   // Another limitation, though one shared with ..._impl(), is that any
     48   // thread_locals that are first initialized after non-thread_local global
     49   // destructors begin to run will not be destroyed.  [basic.start.term] states
     50   // that all thread_local destructors are sequenced before the destruction of
     51   // objects with static storage duration, resulting in a contradiction if a
     52   // thread_local is constructed after that point.  Thus we consider such
     53   // programs ill-formed, and don't bother to run those destructors.  (If the
     54   // program terminates abnormally after such a thread_local is constructed,
     55   // the destructor is not expected to run and thus there is no contradiction.
     56   // So construction still has to work.)
     57 
     58   struct DtorList {
     59     Dtor dtor;
     60     void* obj;
     61     DtorList* next;
     62   };
     63 
     64   // The linked list of thread-local destructors to run
     65   __thread DtorList* dtors = nullptr;
     66   // True if the destructors are currently scheduled to run on this thread
     67   __thread bool dtors_alive = false;
     68   // Used to trigger destructors on thread exit; value is ignored
     69   std::__libcpp_tls_key dtors_key;
     70 
     71   void run_dtors(void*) {
     72     while (auto head = dtors) {
     73       dtors = head->next;
     74       head->dtor(head->obj);
     75       std::free(head);
     76     }
     77 
     78     dtors_alive = false;
     79   }
     80 
     81   struct DtorsManager {
     82     DtorsManager() {
     83       // There is intentionally no matching std::__libcpp_tls_delete call, as
     84       // __cxa_thread_atexit() may be called arbitrarily late (for example, from
     85       // global destructors or atexit() handlers).
     86       if (std::__libcpp_tls_create(&dtors_key, run_dtors) != 0) {
     87         abort_message("std::__libcpp_tls_create() failed in __cxa_thread_atexit()");
     88       }
     89     }
     90 
     91     ~DtorsManager() {
     92       // std::__libcpp_tls_key destructors do not run on threads that call exit()
     93       // (including when the main thread returns from main()), so we explicitly
     94       // call the destructor here.  This runs at exit time (potentially earlier
     95       // if libc++abi is dlclose()'d).  Any thread_locals initialized after this
     96       // point will not be destroyed.
     97       run_dtors(nullptr);
     98     }
     99   };
    100 } // namespace
    101 
    102 #endif // HAVE___CXA_THREAD_ATEXIT_IMPL
    103 
    104 extern "C" {
    105 
    106   _LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(Dtor dtor, void* obj, void* dso_symbol) throw() {
    107 #ifdef HAVE___CXA_THREAD_ATEXIT_IMPL
    108     return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
    109 #else
    110     if (__cxa_thread_atexit_impl) {
    111       return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
    112     } else {
    113       // Initialize the dtors std::__libcpp_tls_key (uses __cxa_guard_*() for
    114       // one-time initialization and __cxa_atexit() for destruction)
    115       static DtorsManager manager;
    116 
    117       if (!dtors_alive) {
    118         if (std::__libcpp_tls_set(dtors_key, &dtors_key) != 0) {
    119           return -1;
    120         }
    121         dtors_alive = true;
    122       }
    123 
    124       auto head = static_cast<DtorList*>(std::malloc(sizeof(DtorList)));
    125       if (!head) {
    126         return -1;
    127       }
    128 
    129       head->dtor = dtor;
    130       head->obj = obj;
    131       head->next = dtors;
    132       dtors = head;
    133 
    134       return 0;
    135     }
    136 #endif // HAVE___CXA_THREAD_ATEXIT_IMPL
    137   }
    138 
    139 } // extern "C"
    140 } // namespace __cxxabiv1
    141