diff --git a/abi.html b/abi.html index b2df8ab..161d3ec 100644 --- a/abi.html +++ b/abi.html @@ -4079,22 +4079,21 @@
-
-The C++ Standard requires that destructors be called for global objects
-when a program exits in the opposite order of construction.
-Most implementations have handled this by calling the C library
-
-
-The runtime library shall maintain a list of termination functions
-with the following information about each:
+The runtime library shall maintain a list of global termination
+functions with the following information about each:
-The representation of this structure is implementation defined.
+Entries in this list need not be unique. If the same function
+is registered multiple times, it is called multiple times as
+described below.
+
+
+The runtime library shall also maintain an analogous list of
+thread-local termination functions for each thread, with
+the same information about each.
+
+
+The representation of these lists is implementation defined.
All references are via the API described below.
+
+
+
-
- The third argument,
-
-After constructing a global (or local static) object,
-that will require destruction on exit,
-a termination function is registered as follows:
-
-The registration function is not called from within the constructor.
+
- The third argument,
-When the user registers exit functions with
-
-When linking any DSO containing a call to
+
+The C++ standard requires calls to exit functions registered with
+
+There is no analogous thread-specific
+The C++ standard does not provide a user interface corresponding
+to
+When linking any DSO containing a call to
+Additionally, DSOs that contain a call to
@@ -4196,8 +4278,10 @@
When the main program calls
@@ -4208,8 +4292,9 @@
-Since 3.3.6 DSO Object Destruction API
+ 3.3.6 Global and Thread-Local Object Destruction API
3.3.6.1 Motivation
atexit
routine to register the destructors.
-This is problematic because the 1999 C Standard only requires that the
-implementation support 32 registered functions,
-although most implementations support many more.
-More important,
-it does not deal at all with the ability in most implementations to
+The C++ Standard requires that destructors be called for global
+objects when a program exits. Most implementations have handled
+this by calling the C library atexit
routine to
+register the destructors.
+This is problematic because the C standard only requires that the
+implementation support 32 registered functions, although most
+implementations support many more. More importantly, it does not
+deal at all with the ability in most implementations to
remove DSOs from a running program image by calling
dlclose
prior to program termination.
@@ -4107,73 +4106,156 @@ 3.3.6.1 Motivation
3.3.6.2 Runtime Data Structure
+3.3.6.2 Runtime Data Structure
void*
operand to be passed to the function.
+void*
handle for the home DSO of the entry (below).
3.3.6.3 Destructors for global objects
+
3.3.6.3 Runtime API
+After constructing an object with static storage duration
+that will require destruction on process exit, a global
+termination function is registered by calling the following
+function:
+
+
+
+extern "C" int __cxa_atexit(void (*f)(void *), void *p, void *d);
d
, must be the value
+&__dso_handle
for the DSO which defines the object;
+see below. The first and second arguments may be chosen at the
+implementation's convenience.
-
f(p)
when the unloading
+of DSO d
is required, including when the process exits.
+The call will occur before the DSO is actually unloaded from the
+process. Calls to global termination functions will be made in the
+reverse order of their registration.
+
-extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d );
-
__cxa_atexit(f,p,d)
,
-is intended to cause the call f(p)
when DSO d
is unloaded,
-before all such termination calls registered before this one.
-It returns zero if registration is successful, nonzero on failure.
+Note that global termination functions may be registered
+concurrently. If the registrations of two separate termination
+functions are not well-ordered by the strongly happens before
+relation, the order in which they are called is unspecified.
__cxa_atexit
returns zero if registration is successful,
+nonzero on failure.
+
+
+3.3.6.4 Destructors for thread-local objects
atexit
calls:
+After constructing an object with thread storage duration
+that will require destruction on process or thread exit,
+a thread-local termination function is registered for the
+current thread by calling the following function:
+
+
+
+extern "C" int __cxa_thread_atexit(void (*f)(void *), void *p, void *d);
d
, must be the value
+&__dso_handle
for the DSO which defines the object;
+see below. The first and second arguments may be chosen at the
+implementation's convenience.
+
atexit
,
-they should be registered with NULL parameters and DSO handles, i.e.
-
- __cxa_atexit ( f, NULL, NULL );
-
atexit
-implementation so that C-only DSOs will nevertheless interact with C++
-programs in a C++-standard-conforming manner.
-No user interface to __cxa_atexit
is supported,
-so the user is not able to register an atexit
function
-with a parameter or a home DSO.
+The runtime library will call f(p)
if the
+registering thread either terminates or exits the process (e.g.
+by calling std::exit
). Calls will be made in the
+reverse order of registration. Calls will be made from the
+registering thread.
__cxa_atexit
,
+If the unloading of a DSO is required other than during process
+exit (e.g. by calling dlclose
), and there are any
+any thread-local termination functions associated with that DSO,
+the behavior is undefined. Some implementations choose to support
+this by delaying the unloading of the DSO until all such functions
+have been called on all threads. Implementations that wish to
+unload the DSO immediately are encouraged to at least call
+thread-local termination functions registered for the current
+thread.
+
+__cxa_thread_atexit
returns zero if registration
+is successful, nonzero on failure.
+
+
+3.3.6.5 User calls to
+
+atexit
atexit
to occur in reverse order of registration,
+appropriately interordered with the destruction of global objects
+according to the completion order of their initialization; see
+[basic.start.term]. It is expected
+that implementations supporting C++ will integrate support for
+__cxa_atexit
into the C library in order to achieve
+these semantics.
+
+atexit
API
+in the C or C++ standards, or in POSIX threads. If there were,
+it would be expected to be appropriately interordered with the
+destruction of thread-local objects. It is currently unclear
+what the appropriate interordering rules are for the destruction
+of thread-local storage such as C11's tss_create
or
+POSIX's pthread_key_create
; these APIs do not
+specify any particular destruction order for multiple keys.
+
+__cxa_atexit
or __cxa_thread_atexit
.
+There is no way to register an atexit
function
+with a parameter or a home DSO.
+
+
+3.3.6.6 Termination
+
+__cxa_atexit
+or __cxa_thread_atexit
,
the linker should define a hidden symbol __dso_handle
,
with a value which is an address in one of the object's segments.
-(It does not matter what address,
-as long as they are different in different DSOs.)
-It should also include a call to the following function in the FINI
+(It does not matter what address, as long as they are different in
+different DSOs.)
+
+__cxa_atexit
++should also include a call to the following function in the FINI
list (to be executed first):
-
-extern "C" void __cxa_finalize ( void *d );
-
The parameter passed should be extern "C" void __cxa_finalize ( void *d );
&__dso_handle
.
3.3.6.3 Runtime API
exit
,
-it must call any remaining __cxa_atexit
-registered functions,
-either by calling __cxa_finalize(NULL)
,
+it must first call any __cxa_thread_atexit
-registered
+functions for the exiting thread.
+Next, it must call any remaining __cxa_atexit
-registered
+functions, either by calling __cxa_finalize(NULL)
,
or by walking the registration list itself.
3.3.6.3 Runtime API
__cxa_atexit
and __cxa_finalize
-must both manipulate the same termination function list,
+Since calls to __cxa_atexit
,
+__cxa_thread_atexit
, and __cxa_finalize
+must manipulate the same termination function lists,
they must be defined in the implementation's runtime library,
rather than in the individual linked objects.