123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- /* Copyright (C) 1991-2019 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sysdep.h>
- #include <libc-lock.h>
- #include "exit.h"
- #include "set-hooks.h"
- DEFINE_HOOK (__libc_atexit, (void))
- /* Initialize the flag that indicates exit function processing
- is complete. See concurrency notes in stdlib/exit.h where
- __exit_funcs_lock is declared. */
- bool __exit_funcs_done = false;
- /* Call all functions registered with `atexit' and `on_exit',
- in the reverse of the order in which they were registered
- perform stdio cleanup, and terminate program execution with STATUS. */
- void
- attribute_hidden
- __run_exit_handlers (int status, struct exit_function_list **listp,
- bool run_list_atexit, bool run_dtors)
- {
- /* First, call the TLS destructors. */
- #ifndef SHARED
- if (&__call_tls_dtors != NULL)
- #endif
- if (run_dtors)
- __call_tls_dtors ();
- /* We do it this way to handle recursive calls to exit () made by
- the functions registered with `atexit' and `on_exit'. We call
- everyone on the list and use the status value in the last
- exit (). */
- while (true)
- {
- struct exit_function_list *cur;
- __libc_lock_lock (__exit_funcs_lock);
- restart:
- cur = *listp;
- if (cur == NULL)
- {
- /* Exit processing complete. We will not allow any more
- atexit/on_exit registrations. */
- __exit_funcs_done = true;
- __libc_lock_unlock (__exit_funcs_lock);
- break;
- }
- while (cur->idx > 0)
- {
- struct exit_function *const f = &cur->fns[--cur->idx];
- const uint64_t new_exitfn_called = __new_exitfn_called;
- /* Unlock the list while we call a foreign function. */
- __libc_lock_unlock (__exit_funcs_lock);
- switch (f->flavor)
- {
- void (*atfct) (void);
- void (*onfct) (int status, void *arg);
- void (*cxafct) (void *arg, int status);
- case ef_free:
- case ef_us:
- break;
- case ef_on:
- onfct = f->func.on.fn;
- #ifdef PTR_DEMANGLE
- PTR_DEMANGLE (onfct);
- #endif
- onfct (status, f->func.on.arg);
- break;
- case ef_at:
- atfct = f->func.at;
- #ifdef PTR_DEMANGLE
- PTR_DEMANGLE (atfct);
- #endif
- atfct ();
- break;
- case ef_cxa:
- /* To avoid dlclose/exit race calling cxafct twice (BZ 22180),
- we must mark this function as ef_free. */
- f->flavor = ef_free;
- cxafct = f->func.cxa.fn;
- #ifdef PTR_DEMANGLE
- PTR_DEMANGLE (cxafct);
- #endif
- cxafct (f->func.cxa.arg, status);
- break;
- }
- /* Re-lock again before looking at global state. */
- __libc_lock_lock (__exit_funcs_lock);
- if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called))
- /* The last exit function, or another thread, has registered
- more exit functions. Start the loop over. */
- goto restart;
- }
- *listp = cur->next;
- if (*listp != NULL)
- /* Don't free the last element in the chain, this is the statically
- allocate element. */
- free (cur);
- __libc_lock_unlock (__exit_funcs_lock);
- }
- if (run_list_atexit)
- RUN_HOOK (__libc_atexit, ());
- _exit (status);
- }
- void
- exit (int status)
- {
- __run_exit_handlers (status, &__exit_funcs, true, true);
- }
- libc_hidden_def (exit)
|