4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 * Copyright 2016 Joyent, Inc.
29 /* Copyright (c) 1988 AT&T */
30 /* All Rights Reserved */
32 #pragma weak _atexit = atexit
35 #include "thr_uberdata.h"
41 * Note that memory is managed by lmalloc()/lfree().
43 * Among other reasons, this is occasioned by the insistence of our
44 * brothers sh(1) and csh(1) that they can do malloc, etc., better than
45 * libc can. Those programs define their own malloc routines, and
46 * initialize the underlying mechanism in main(). This means that calls
47 * to malloc occuring before main will crash. The loader calls atexit(3C)
48 * before calling main, so we'd better avoid malloc() when it does.
50 * Another reason for using lmalloc()/lfree() is that the atexit()
51 * list must transcend all link maps. See the Linker and Libraries
52 * Guide for information on alternate link maps.
54 * See "thr_uberdata.h" for the definitions of structures used here.
57 static int in_range(void *, Lc_addr_range_t
[], uint_t count
);
59 extern caddr_t
_getfp(void);
62 * exitfns_lock is declared to be a recursive mutex so that we
63 * can hold it while calling out to the registered functions.
64 * If they call back to us, we are self-consistent and everything
65 * works, even the case of calling exit() from functions called
66 * by _exithandle() (recursive exit()). All that is required is
67 * that the registered functions actually return (no longjmp()s).
69 * Because exitfns_lock is declared to be a recursive mutex, we
70 * cannot use it with lmutex_lock()/lmutex_unlock() and we must
71 * use mutex_lock()/mutex_unlock(). This means that atexit()
72 * and exit() are not async-signal-safe. We make them fork1-safe
73 * via the atexit_locks()/atexit_unlocks() functions, called from
74 * libc_prepare_atfork()/libc_child_atfork()/libc_parent_atfork()
78 * atexit_locks() and atexit_unlocks() are called on every link map.
79 * Do not use curthread->ul_uberdata->atexit_root for these.
84 (void) mutex_lock(&__uberdata
.atexit_root
.exitfns_lock
);
85 (void) mutex_lock(&__uberdata
.quickexit_root
.exitfns_lock
);
91 (void) mutex_unlock(&__uberdata
.quickexit_root
.exitfns_lock
);
92 (void) mutex_unlock(&__uberdata
.atexit_root
.exitfns_lock
);
97 * This is called via atexit() before the primordial thread is fully set up.
98 * Be careful about dereferencing self->ul_uberdata->atexit_root.
101 __cxa_atexit(void (*hdlr
)(void *), void *arg
, void *dso
)
107 if ((p
= lmalloc(sizeof (_exthdlr_t
))) == NULL
)
110 if ((self
= __curthread()) == NULL
)
111 arp
= &__uberdata
.atexit_root
;
113 arp
= &self
->ul_uberdata
->atexit_root
;
114 (void) mutex_lock(&arp
->exitfns_lock
);
123 (void) mutex_unlock(&arp
->exitfns_lock
);
128 atexit(void (*func
)(void))
130 return (__cxa_atexit((_exithdlr_func_t
)func
, NULL
, NULL
));
134 * Note that we may be entered recursively, as we'll call __cxa_finalize(0) at
135 * exit, one of our handlers is ld.so.1`atexit_fini, and libraries may call
136 * __cxa_finalize(__dso_handle) from their _fini.
139 __cxa_finalize(void *dso
)
141 atexit_root_t
*arp
= &curthread
->ul_uberdata
->atexit_root
;
145 /* disable cancellation while running atexit handlers */
146 (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, &cancel_state
);
147 (void) mutex_lock(&arp
->exitfns_lock
);
152 if ((dso
== NULL
) || (p
->dso
== dso
)) {
159 lfree(p
, sizeof (_exthdlr_t
));
168 (void) mutex_unlock(&arp
->exitfns_lock
);
169 (void) pthread_setcancelstate(cancel_state
, NULL
);
175 atexit_root_t
*arp
= &curthread
->ul_uberdata
->atexit_root
;
177 arp
->exit_frame_monitor
= _getfp() + STACK_BIAS
;
178 __cxa_finalize(NULL
);
182 * _get_exit_frame_monitor is called by the C++ runtimes.
185 _get_exit_frame_monitor(void)
187 atexit_root_t
*arp
= &curthread
->ul_uberdata
->atexit_root
;
188 return (&arp
->exit_frame_monitor
);
192 * The following is a routine which the loader (ld.so.1) calls when it
193 * processes a dlclose call on an object. It resets all signal handlers
194 * which fall within the union of the ranges specified by the elements
195 * of the array range to SIG_DFL.
198 _preexec_sig_unload(Lc_addr_range_t range
[], uint_t count
)
200 uberdata_t
*udp
= curthread
->ul_uberdata
;
203 struct sigaction
*sap
;
204 struct sigaction oact
;
207 for (sig
= 1; sig
< NSIG
; sig
++) {
208 sap
= (struct sigaction
*)&udp
->siguaction
[sig
].sig_uaction
;
210 handler
= sap
->sa_handler
;
211 if (handler
!= SIG_DFL
&& handler
!= SIG_IGN
&&
212 in_range((void *)handler
, range
, count
)) {
213 rwlp
= &udp
->siguaction
[sig
].sig_lock
;
215 if (handler
!= sap
->sa_handler
) {
219 sap
->sa_handler
= SIG_DFL
;
220 sap
->sa_flags
= SA_SIGINFO
;
221 (void) sigemptyset(&sap
->sa_mask
);
222 if (__sigaction(sig
, NULL
, &oact
) == 0 &&
223 oact
.sa_handler
!= SIG_DFL
&&
224 oact
.sa_handler
!= SIG_IGN
)
225 (void) __sigaction(sig
, sap
, NULL
);
232 * The following is a routine which the loader (ld.so.1) calls when it
233 * processes a dlclose call on an object. It cancels all atfork() entries
234 * whose prefork, parent postfork, or child postfork functions fall within
235 * the union of the ranges specified by the elements of the array range.
238 _preexec_atfork_unload(Lc_addr_range_t range
[], uint_t count
)
240 ulwp_t
*self
= curthread
;
241 uberdata_t
*udp
= self
->ul_uberdata
;
248 (void) mutex_lock(&udp
->atfork_lock
);
249 if ((atfork_q
= udp
->atforklist
) != NULL
) {
255 if (((func
= atfp
->prepare
) != NULL
&&
256 in_range((void *)func
, range
, count
)) ||
257 ((func
= atfp
->parent
) != NULL
&&
258 in_range((void *)func
, range
, count
)) ||
259 ((func
= atfp
->child
) != NULL
&&
260 in_range((void *)func
, range
, count
))) {
263 * dlclose() called from a fork handler.
264 * Deleting the entry would wreak havoc.
265 * Just null out the function pointers
266 * and leave the entry in place.
268 atfp
->prepare
= NULL
;
273 if (atfp
== atfork_q
) {
274 /* deleting the list head member */
275 udp
->atforklist
= atfork_q
= next
;
278 atfp
->forw
->back
= atfp
->back
;
279 atfp
->back
->forw
= atfp
->forw
;
280 lfree(atfp
, sizeof (atfork_t
));
281 if (atfp
== atfork_q
) {
282 /* we deleted the whole list */
283 udp
->atforklist
= NULL
;
287 } while ((atfp
= next
) != atfork_q
|| start_again
);
289 (void) mutex_unlock(&udp
->atfork_lock
);
293 * The following is a routine which the loader (ld.so.1) calls when it
294 * processes a dlclose call on an object. It sets the destructor
295 * function pointer to NULL for all keys whose destructors fall within
296 * the union of the ranges specified by the elements of the array range.
297 * We don't assign TSD_UNALLOCATED (the equivalent of pthread_key_destroy())
298 * because the thread may use the key's TSD further on in fini processing.
301 _preexec_tsd_unload(Lc_addr_range_t range
[], uint_t count
)
303 tsd_metadata_t
*tsdm
= &curthread
->ul_uberdata
->tsd_metadata
;
304 void (*func
)(void *);
307 lmutex_lock(&tsdm
->tsdm_lock
);
308 for (key
= 1; key
< tsdm
->tsdm_nused
; key
++) {
309 if ((func
= tsdm
->tsdm_destro
[key
]) != NULL
&&
310 func
!= TSD_UNALLOCATED
&&
311 in_range((void *)func
, range
, count
))
312 tsdm
->tsdm_destro
[key
] = NULL
;
314 lmutex_unlock(&tsdm
->tsdm_lock
);
318 * The following is a routine which the loader (ld.so.1) calls when it
319 * processes dlclose calls on objects with atexit registrations. It
320 * executes the exit handlers that fall within the union of the ranges
321 * specified by the elements of the array range in the REVERSE ORDER of
322 * their registration. Do not change this characteristic; it is REQUIRED
326 _preexec_exit_handlers(Lc_addr_range_t range
[], uint_t count
)
328 atexit_root_t
*arp
= &curthread
->ul_uberdata
->atexit_root
;
329 _exthdlr_t
*o
; /* previous node */
330 _exthdlr_t
*p
; /* this node */
333 /* disable cancellation while running atexit handlers */
334 (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, &cancel_state
);
335 (void) mutex_lock(&arp
->exitfns_lock
);
340 * We call even CXA handlers of functions present in the
341 * library being unloaded. The specification isn't
342 * particularly clear on this, and this seems the most sane.
343 * This is the behaviour of FreeBSD 9.1 (GNU libc leaves the
344 * handler on the exit list, and crashes at exit time).
346 * This won't cause handlers to be called twice, because
347 * anything called from a __cxa_finalize call from the
348 * language runtime will have been removed from the list.
350 if (in_range((void *)p
->hdlr
, range
, count
)) {
351 /* We need to execute this one */
357 lfree(p
, sizeof (_exthdlr_t
));
365 (void) mutex_unlock(&arp
->exitfns_lock
);
366 (void) pthread_setcancelstate(cancel_state
, NULL
);
368 _preexec_tsd_unload(range
, count
);
369 _preexec_atfork_unload(range
, count
);
370 _preexec_sig_unload(range
, count
);
376 in_range(void *addr
, Lc_addr_range_t ranges
[], uint_t count
)
380 for (idx
= 0; idx
< count
; idx
++) {
381 if (addr
>= ranges
[idx
].lb
&&
382 addr
< ranges
[idx
].ub
) {
391 at_quick_exit(void (*func
)(void))
394 quickexit_root_t
*arp
;
397 if ((p
= lmalloc(sizeof (_qexthdlr_t
))) == NULL
)
400 if ((self
= __curthread()) == NULL
) {
401 arp
= &__uberdata
.quickexit_root
;
403 arp
= &self
->ul_uberdata
->quickexit_root
;
404 (void) mutex_lock(&arp
->exitfns_lock
);
411 (void) mutex_unlock(&arp
->exitfns_lock
);
417 quick_exit(int status
)
419 quickexit_root_t
*qrp
= &curthread
->ul_uberdata
->quickexit_root
;
423 (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, &cancel_state
);
424 (void) mutex_lock(&qrp
->exitfns_lock
);
430 lfree(p
, sizeof (_qexthdlr_t
));
434 (void) mutex_unlock(&qrp
->exitfns_lock
);
435 (void) pthread_setcancelstate(cancel_state
, NULL
);