If _DL_FINI_CRT_COMPAT is defined, _dl_fini is setup to run at exit via atexit(), but this makes it run _before_ the fini (__app_fini()) of the app, causing stuff like sandbox that frees structs, etc via its fini to segfault. Relevant back-trace: (gdb) bt #0 0x400cb62c in free () from /lib/libc.so.0 #1 0x4000b3da in before_syscall (func=0x4000bd63 "unlink", file=0x80dca90 "/tmp/groff35k2OB") at libsandbox.c:1362 #2 0x40009c28 in unlink (pathname=0x80dca90 "/tmp/groff35k2OB") at libsandbox.c:657 #3 0x0805e34c in xtmpfile_list_init::~xtmpfile_list_init () #4 0x0805e557 in __static_initialization_and_destruction_0 () #5 0x0805e5a8 in global destructors keyed to tmpfile_prefix () #6 0x080494d6 in __do_global_dtors_aux () #7 0x0805e5fc in _fini () #8 0x400c91ba in exit () from /lib/libc.so.0 #9 0x400a1f7d in __uClibc_start_main () from /lib/libc.so.0 #10 0x080494a8 in _start () #11 0x00000003 in ?? () #12 0xbffff744 in ?? () #13 0xbffff754 in ?? () #14 0x08048ff8 in ?? () #15 0x0805e5e8 in __do_global_ctors_aux () #16 0x00000000 in ?? () --- libc/stdlib/atexit.c +++ libc/stdlib/atexit.c @@ -221,6 +221,7 @@ #ifdef __UCLIBC_CTOR_DTOR__ extern void (*__app_fini)(void); #endif +extern void (*__dl_fini)(void); /* * Normal program termination @@ -238,6 +239,8 @@ if (__app_fini != NULL) (__app_fini)(); #endif + if (__dl_fini != NULL) + (__dl_fini)(); /* If we are using stdio, try to shut it down. At the very least, * this will attempt to commit all buffered writes. It may also --- libc/misc/internals/__uClibc_main.c +++ libc/misc/internals/__uClibc_main.c @@ -158,6 +158,13 @@ void (*__app_fini)(void) = NULL; #endif +void attribute_hidden (*__dl_fini)(void) = NULL; +void _set__dl_fini(void *fini_func) +{ + if (fini_func != NULL) + __dl_fini = fini_func; +} + /* __uClibc_start_main is the new main stub for uClibc. This function is * called from crt0 (version 0.9.16 or newer), after ALL shared libraries * are initialized, just before we call the application's main function. --- ldso/ldso/ldso.c +++ ldso/ldso/ldso.c @@ -98,7 +98,7 @@ struct elf_resolve *app_tpnt = &app_tpnt_tmp; struct r_debug *debug_addr; unsigned long *lpnt; - int (*_dl_atexit) (void *); + void (*__set__dl_fini) (void *); unsigned long *_dl_envp; /* The environment address */ ElfW(Addr) relro_addr = 0; size_t relro_size = 0; @@ -798,7 +798,7 @@ } #endif - _dl_atexit = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT); + __set__dl_fini = (void (*)(void *)) (intptr_t) _dl_find_hash("_set__dl_fini", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT); #if defined (__SUPPORT_LD_DEBUG__) _dl_on_exit = (int (*)(void (*)(int, void *),void*)) (intptr_t) _dl_find_hash("on_exit", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT); @@ -829,11 +829,11 @@ (*dl_elf_func) (); } tpnt->init_flag |= FINI_FUNCS_CALLED; - if (_dl_atexit && tpnt->dynamic_info[DT_FINI]) { + if (__set__dl_fini && tpnt->dynamic_info[DT_FINI]) { void (*dl_elf_func) (void); dl_elf_func = (void (*)(void)) (intptr_t) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]); - (*_dl_atexit) (dl_elf_func); + (*__set__dl_fini) (dl_elf_func); #if defined (__SUPPORT_LD_DEBUG__) if(_dl_debug && _dl_on_exit) { (*_dl_on_exit)(debug_fini, tpnt->libname); @@ -842,7 +842,7 @@ } #if defined (__SUPPORT_LD_DEBUG__) else { - if (!_dl_atexit) + if (!__set__dl_fini) _dl_dprintf(_dl_debug_file, "%s: The address of atexit () is 0x0.\n", tpnt->libname); } #endif