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.
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
30 #pragma weak _atexit = atexit
33 #include "thr_uberdata.h"
39 * Note that memory is managed by lmalloc()/lfree().
41 * Among other reasons, this is occasioned by the insistence of our
42 * brothers sh(1) and csh(1) that they can do malloc, etc., better than
43 * libc can. Those programs define their own malloc routines, and
44 * initialize the underlying mechanism in main(). This means that calls
45 * to malloc occuring before main will crash. The loader calls atexit(3C)
46 * before calling main, so we'd better avoid malloc() when it does.
48 * Another reason for using lmalloc()/lfree() is that the atexit()
49 * list must transcend all link maps. See the Linker and Libraries
50 * Guide for information on alternate link maps.
52 * See "thr_uberdata.h" for the definitions of structures used here.
55 static int in_range(void *, Lc_addr_range_t
[], uint_t count
);
57 extern caddr_t
_getfp(void);
60 * exitfns_lock is declared to be a recursive mutex so that we
61 * can hold it while calling out to the registered functions.
62 * If they call back to us, we are self-consistent and everything
63 * works, even the case of calling exit() from functions called
64 * by _exithandle() (recursive exit()). All that is required is
65 * that the registered functions actually return (no longjmp()s).
67 * Because exitfns_lock is declared to be a recursive mutex, we
68 * cannot use it with lmutex_lock()/lmutex_unlock() and we must
69 * use mutex_lock()/mutex_unlock(). This means that atexit()
70 * and exit() are not async-signal-safe. We make them fork1-safe
71 * via the atexit_locks()/atexit_unlocks() functions, called from
72 * libc_prepare_atfork()/libc_child_atfork()/libc_parent_atfork()
76 * atexit_locks() and atexit_unlocks() are called on every link map.
77 * Do not use curthread->ul_uberdata->atexit_root for these.
82 (void) mutex_lock(&__uberdata
.atexit_root
.exitfns_lock
);
88 (void) mutex_unlock(&__uberdata
.atexit_root
.exitfns_lock
);
93 * This is called via atexit() before the primordial thread is fully set up.
94 * Be careful about dereferencing self->ul_uberdata->atexit_root.
97 __cxa_atexit(void (*hdlr
)(void *), void *arg
, void *dso
)
103 if ((p
= lmalloc(sizeof (_exthdlr_t
))) == NULL
)
106 if ((self
= __curthread()) == NULL
)
107 arp
= &__uberdata
.atexit_root
;
109 arp
= &self
->ul_uberdata
->atexit_root
;
110 (void) mutex_lock(&arp
->exitfns_lock
);
119 (void) mutex_unlock(&arp
->exitfns_lock
);
124 atexit(void (*func
)(void))
126 return (__cxa_atexit((_exithdlr_func_t
)func
, NULL
, NULL
));
130 * Note that we may be entered recursively, as we'll call __cxa_finalize(0) at
131 * exit, one of our handlers is ld.so.1`atexit_fini, and libraries may call
132 * __cxa_finalize(__dso_handle) from their _fini.
135 __cxa_finalize(void *dso
)
137 atexit_root_t
*arp
= &curthread
->ul_uberdata
->atexit_root
;
141 /* disable cancellation while running atexit handlers */
142 (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, &cancel_state
);
143 (void) mutex_lock(&arp
->exitfns_lock
);
148 if ((dso
== NULL
) || (p
->dso
== dso
)) {
155 lfree(p
, sizeof (_exthdlr_t
));
164 (void) mutex_unlock(&arp
->exitfns_lock
);
165 (void) pthread_setcancelstate(cancel_state
, NULL
);
171 atexit_root_t
*arp
= &curthread
->ul_uberdata
->atexit_root
;
173 arp
->exit_frame_monitor
= _getfp() + STACK_BIAS
;
174 __cxa_finalize(NULL
);
178 * _get_exit_frame_monitor is called by the C++ runtimes.
181 _get_exit_frame_monitor(void)
183 atexit_root_t
*arp
= &curthread
->ul_uberdata
->atexit_root
;
184 return (&arp
->exit_frame_monitor
);
188 * The following is a routine which the loader (ld.so.1) calls when it
189 * processes a dlclose call on an object. It resets all signal handlers
190 * which fall within the union of the ranges specified by the elements
191 * of the array range to SIG_DFL.
194 _preexec_sig_unload(Lc_addr_range_t range
[], uint_t count
)
196 uberdata_t
*udp
= curthread
->ul_uberdata
;
199 struct sigaction
*sap
;
200 struct sigaction oact
;
203 for (sig
= 1; sig
< NSIG
; sig
++) {
204 sap
= (struct sigaction
*)&udp
->siguaction
[sig
].sig_uaction
;
206 handler
= sap
->sa_handler
;
207 if (handler
!= SIG_DFL
&& handler
!= SIG_IGN
&&
208 in_range((void *)handler
, range
, count
)) {
209 rwlp
= &udp
->siguaction
[sig
].sig_lock
;
211 if (handler
!= sap
->sa_handler
) {
215 sap
->sa_handler
= SIG_DFL
;
216 sap
->sa_flags
= SA_SIGINFO
;
217 (void) sigemptyset(&sap
->sa_mask
);
218 if (__sigaction(sig
, NULL
, &oact
) == 0 &&
219 oact
.sa_handler
!= SIG_DFL
&&
220 oact
.sa_handler
!= SIG_IGN
)
221 (void) __sigaction(sig
, sap
, NULL
);
228 * The following is a routine which the loader (ld.so.1) calls when it
229 * processes a dlclose call on an object. It cancels all atfork() entries
230 * whose prefork, parent postfork, or child postfork functions fall within
231 * the union of the ranges specified by the elements of the array range.
234 _preexec_atfork_unload(Lc_addr_range_t range
[], uint_t count
)
236 ulwp_t
*self
= curthread
;
237 uberdata_t
*udp
= self
->ul_uberdata
;
244 (void) mutex_lock(&udp
->atfork_lock
);
245 if ((atfork_q
= udp
->atforklist
) != NULL
) {
251 if (((func
= atfp
->prepare
) != NULL
&&
252 in_range((void *)func
, range
, count
)) ||
253 ((func
= atfp
->parent
) != NULL
&&
254 in_range((void *)func
, range
, count
)) ||
255 ((func
= atfp
->child
) != NULL
&&
256 in_range((void *)func
, range
, count
))) {
259 * dlclose() called from a fork handler.
260 * Deleting the entry would wreak havoc.
261 * Just null out the function pointers
262 * and leave the entry in place.
264 atfp
->prepare
= NULL
;
269 if (atfp
== atfork_q
) {
270 /* deleting the list head member */
271 udp
->atforklist
= atfork_q
= next
;
274 atfp
->forw
->back
= atfp
->back
;
275 atfp
->back
->forw
= atfp
->forw
;
276 lfree(atfp
, sizeof (atfork_t
));
277 if (atfp
== atfork_q
) {
278 /* we deleted the whole list */
279 udp
->atforklist
= NULL
;
283 } while ((atfp
= next
) != atfork_q
|| start_again
);
285 (void) mutex_unlock(&udp
->atfork_lock
);
289 * The following is a routine which the loader (ld.so.1) calls when it
290 * processes a dlclose call on an object. It sets the destructor
291 * function pointer to NULL for all keys whose destructors fall within
292 * the union of the ranges specified by the elements of the array range.
293 * We don't assign TSD_UNALLOCATED (the equivalent of pthread_key_destroy())
294 * because the thread may use the key's TSD further on in fini processing.
297 _preexec_tsd_unload(Lc_addr_range_t range
[], uint_t count
)
299 tsd_metadata_t
*tsdm
= &curthread
->ul_uberdata
->tsd_metadata
;
300 void (*func
)(void *);
303 lmutex_lock(&tsdm
->tsdm_lock
);
304 for (key
= 1; key
< tsdm
->tsdm_nused
; key
++) {
305 if ((func
= tsdm
->tsdm_destro
[key
]) != NULL
&&
306 func
!= TSD_UNALLOCATED
&&
307 in_range((void *)func
, range
, count
))
308 tsdm
->tsdm_destro
[key
] = NULL
;
310 lmutex_unlock(&tsdm
->tsdm_lock
);
314 * The following is a routine which the loader (ld.so.1) calls when it
315 * processes dlclose calls on objects with atexit registrations. It
316 * executes the exit handlers that fall within the union of the ranges
317 * specified by the elements of the array range in the REVERSE ORDER of
318 * their registration. Do not change this characteristic; it is REQUIRED
322 _preexec_exit_handlers(Lc_addr_range_t range
[], uint_t count
)
324 atexit_root_t
*arp
= &curthread
->ul_uberdata
->atexit_root
;
325 _exthdlr_t
*o
; /* previous node */
326 _exthdlr_t
*p
; /* this node */
329 /* disable cancellation while running atexit handlers */
330 (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, &cancel_state
);
331 (void) mutex_lock(&arp
->exitfns_lock
);
336 * We call even CXA handlers of functions present in the
337 * library being unloaded. The specification isn't
338 * particularly clear on this, and this seems the most sane.
339 * This is the behaviour of FreeBSD 9.1 (GNU libc leaves the
340 * handler on the exit list, and crashes at exit time).
342 * This won't cause handlers to be called twice, because
343 * anything called from a __cxa_finalize call from the
344 * language runtime will have been removed from the list.
346 if (in_range((void *)p
->hdlr
, range
, count
)) {
347 /* We need to execute this one */
353 lfree(p
, sizeof (_exthdlr_t
));
361 (void) mutex_unlock(&arp
->exitfns_lock
);
362 (void) pthread_setcancelstate(cancel_state
, NULL
);
364 _preexec_tsd_unload(range
, count
);
365 _preexec_atfork_unload(range
, count
);
366 _preexec_sig_unload(range
, count
);
372 in_range(void *addr
, Lc_addr_range_t ranges
[], uint_t count
)
376 for (idx
= 0; idx
< count
; idx
++) {
377 if (addr
>= ranges
[idx
].lb
&&
378 addr
< ranges
[idx
].ub
) {