summaryrefslogtreecommitdiff
path: root/src/exit
AgeCommit message (Collapse)AuthorFilesLines
2020-11-11lift child restrictions after multi-threaded forkRich Felker2-0/+4
as the outcome of Austin Group tracker issue #62, future editions of POSIX have dropped the requirement that fork be AS-safe. this allows but does not require implementations to synchronize fork with internal locks and give forked children of multithreaded parents a partly or fully unrestricted execution environment where they can continue to use the standard library (per POSIX, they can only portably use AS-safe functions). up until recently, taking this allowance did not seem desirable. however, commit 8ed2bd8bfcb4ea6448afb55a941f4b5b2b0398c0 exposed the extent to which applications and libraries are depending on the ability to use malloc and other non-AS-safe interfaces in MT-forked children, by converting latent very-low-probability catastrophic state corruption into predictable deadlock. dealing with the fallout has been a huge burden for users/distros. while it looks like most of the non-portable usage in applications could be fixed given sufficient effort, at least some of it seems to occur in language runtimes which are exposing the ability to run unrestricted code in the child as part of the contract with the programmer. any attempt at fixing such contracts is not just a technical problem but a social one, and is probably not tractable. this patch extends the fork function to take locks for all libc singletons in the parent, and release or reset those locks in the child, so that when the underlying fork operation takes place, the state protected by these locks is consistent and ready for the child to use. locking is skipped in the case where the parent is single-threaded so as not to interfere with legacy AS-safety property of fork in single-threaded programs. lock order is mostly arbitrary, but the malloc locks (including bump allocator in case it's used) must be taken after the locks on any subsystems that might use malloc, and non-AS-safe locks cannot be taken while the thread list lock is held, imposing a requirement that it be taken last.
2020-11-11convert malloc use under libc-internal locks to use internal allocatorRich Felker1-0/+5
this change lifts undocumented restrictions on calls by replacement mallocs to libc functions that might take these locks, and sets the stage for lifting restrictions on the child execution environment after multithreaded fork. care is taken to #define macros to replace all four functions (malloc, calloc, realloc, free) even if not all of them will be used, using an undefined symbol name for the ones intended not to be used so that any inadvertent future use will be caught at compile time rather than directed to the wrong implementation.
2020-10-14remove incorrect fflush from assert failure handlerRich Felker1-1/+0
assert is not specified to flush open stdio streams, and doing so can block indefinitely waiting for a lock already held or an output operation to a file that can't accept more output until an unsatisfiable condition is met.
2020-10-14move __abort_lock to its own file and drop pointless weak_alias trickRich Felker2-2/+3
the dummy definition of __abort_lock in sigaction.c was performing exactly the same role that putting the lock in its own source file could and should have been used to achieve. while we're moving it, give it a proper declaration.
2018-09-12split internal lock API out of libc.h, creating lock.hRich Felker3-1/+3
this further reduces the number of source files which need to include libc.h and thereby be potentially exposed to libc global state and internals. this will also facilitate further improvements like adding an inline fast-path, if we want to do so later.
2018-09-05define and use internal macros for hidden visibility, weak refsRich Felker2-4/+2
this cleans up what had become widespread direct inline use of "GNU C" style attributes directly in the source, and lowers the barrier to increased use of hidden visibility, which will be useful to recovering some of the efficiency lost when the protected visibility hack was dropped in commit dc2f368e565c37728b0d620380b849c3a1ddd78f, especially on archs where the PLT ABI is costly.
2018-09-01always terminate by SIGABRT when abort is calledRich Felker1-0/+19
Linux makes this surprisingly difficult, but it can be done. the trick here is using the fact that we control the implementation of sigaction to prevent changing the disposition of SIGABRT to anything but SIG_DFL after abort has tried and failed to terminate the process simply by calling raise(SIGABRT).
2018-01-09revise the definition of multiple basic locks in the codeJens Gustedt2-2/+2
In all cases this is just a change from two volatile int to one.
2017-12-14fix data race in at_quick_exitRich Felker1-3/+4
aside from theoretical arbitrary results due to UB, this could practically cause unbounded overflow of static array if hit, but hitting it depends on having more than 32 calls to at_quick_exit and having them sufficiently often.
2016-08-30restore _Noreturn to __assert_failRich Felker1-1/+1
this reverts commit 2c1f8fd5da3306fd7c8a2267467e44eb61f12dd4. without the _Noreturn attribute, the compiler cannot use asserts to perform reachability/range analysis. this leads to missed optimizations and spurious warnings. the original backtrace problem that prompted the removal of _Noreturn was not clearly documented at the time, but it seems to happen only when libc was built without -g, which also breaks many other backtracing cases.
2016-07-03improve abort fallback behavior when raising SIGABRT fails to terminateRich Felker1-1/+5
these changes still do not yield a fully-conforming abort, but they fix two known issues: - per POSIX, termination via SIGKILL is not "abnormal", but both ISO C and POSIX require abort to yield abnormal termination. - raising SIGKILL fails to do anything to pid 1 in some containers. now, the trapping instruction produced by a_crash() is expected to produce abnormal termination, without the risk of invoking a signal handler since SIGILL and SIGSEGV are blocked, and _Exit, which contains an infinite loop analogous to the one being removed from abort itself, is used as a last resort. this implementation still fails to produce an exit status as if the process terminated via SIGABRT in cases where SIGABRT is blocked or ignored, but fixing that is not easy; the obvious pseudo-solutions all have subtle race conditions where a concurrent fork or exec can expose incorrect signal state.
2016-01-22move arm-specific translation units out of arch/arm/src, to src/*/armRich Felker1-0/+6
this is possible with the new build system that allows src/*/$(ARCH)/* files which do not shadow a file in the parent directory, and yields a more logical organization. eventually it will be possible to remove arch/*/src from the build system.
2015-11-19remove undef weak refs to init/fini array symbols in libc.soRich Felker1-4/+4
commit ad1cd43a86645ba2d4f7c8747240452a349d6bc1 eliminated preprocessor-level omission of references to the init/fini array symbols from object files going into libc.so. the references are weak, and the intent was that the linker would resolve them to zero in libc.so, but instead it leaves undefined references that could be satisfied at runtime. normally these references would be harmless, since the code using them does not even get executed, but some older binutils versions produce a linking error: when linking a program against libc.so, ld first tries to use the hidden init/fini array symbols produced by the linker script to satisfy the references in libc.so, then produces an error because the definitions are hidden. ideally ld would have already provided definitions of these symbols when linking libc.so, but the linker script for -shared omits them. to avoid this situation, the dynamic linker now provides its own dummy definitions of the init/fini array symbols for libc.so. since they are hidden, everything binds at ld time and no references remain in the dynamic symbol table. with modern binutils and --gc-sections, both the dummy empty array objects and the code referencing them get dropped at link time, anyway. the _init and _fini symbols are also switched back to using weak definitions rather than weak references since the latter behave somewhat problematically in general, and the weak definition approach was known to work well.
2015-11-11unify static and dynamic libc init/fini code pathsRich Felker1-10/+10
use weak definitions that the dynamic linker can override instead of preprocessor conditionals on SHARED so that the same libc start and exit code can be used for both static and dynamic linking.
2015-07-24fix atexit when it is called from an atexit handlerRich Felker1-12/+9
The old code accepted atexit handlers after exit, but did not run them reliably. C11 seems to explicitly allow atexit to fail (and report such failure) in this case, but this situation can easily come up in C++ if a destructor has a local static object with a destructor so it should be handled. Note that the memory usage can grow linearly with the overall number of registered atexit handlers instead of with the worst case list length. (This only matters if atexit handlers keep registering atexit handlers which should not happen in practice). Commit message/rationale based on text by Szabolcs Nagy.
2015-03-03make all objects used with atomic operations volatileRich Felker2-2/+2
the memory model we use internally for atomics permits plain loads of values which may be subject to concurrent modification without requiring that a special load function be used. since a compiler is free to make transformations that alter the number of loads or the way in which loads are performed, the compiler is theoretically free to break this usage. the most obvious concern is with atomic cas constructs: something of the form tmp=*p;a_cas(p,tmp,f(tmp)); could be transformed to a_cas(p,*p,f(*p)); where the latter is intended to show multiple loads of *p whose resulting values might fail to be equal; this would break the atomicity of the whole operation. but even more fundamental breakage is possible. with the changes being made now, objects that may be modified by atomics are modeled as volatile, and the atomic operations performed on them by other threads are modeled as asynchronous stores by hardware which happens to be acting on the request of another thread. such modeling of course does not itself address memory synchronization between cores/cpus, but that aspect was already handled. this all seems less than ideal, but it's the best we can do without mandating a C11 compiler and using the C11 model for atomics. in the case of pthread_once_t, the ABI type of the underlying object is not volatile-qualified. so we are assuming that accessing the object through a volatile-qualified lvalue via casts yields volatile access semantics. the language of the C standard is somewhat unclear on this matter, but this is an assumption the linux kernel also makes, and seems to be the correct interpretation of the standard.
2014-07-17remove useless infinite loop from end of exit functionRich Felker1-1/+0
this was originally added as a cheap but portable way to quell warnings about reaching the end of a function that does not return, but since _Exit is marked _Noreturn, it's not needed. removing it makes the call to _Exit into a tail call and shaves off a few bytes of code from minimal static programs.
2014-07-16simplify __stdio_exit static linking logicRich Felker1-5/+4
the purpose of this logic is to avoid linking __stdio_exit unless any stdio reads (which might require repositioning the file offset at exit time) or writes (which might require flushing at exit time) could have been performed. previously, exit called two wrapper functions for __stdio_exit named __flush_on_exit and __seek_on_exit. both of these functions actually performed both tasks (seek and flushing) by calling the underlying __stdio_exit. in order to avoid doing this twice, an overridable data object __towrite_used was used to cause __seek_on_exit to act as a nop when __towrite was linked. now, exit only makes one call, directly to __stdio_exit. this is satisfiable by a weak dummy definition in exit.c, but the real definition is pulled in by either __toread.c or __towrite.c through their referencing a symbol which is defined only in __stdio_exit.c.
2014-05-29remove useless synchronization in exit and quick_exitRich Felker2-11/+0
calling exit more than once invokes undefined behavior. in some cases it's desirable to detect undefined behavior and diagnose it via a predictable crash, but the code here was silently covering up an uncommon case (exit from more than one thread) and turning a much more common case (recursive calls to exit) into a permanent hang.
2013-12-12include cleanups: remove unused headers and add feature test macrosSzabolcs Nagy2-4/+1
2013-07-21add support for init/fini array in main program, and greatly simplifyRich Felker1-2/+14
modern (4.7.x and later) gcc uses init/fini arrays, rather than the legacy _init/_fini function pasting and crtbegin/crtend ctors/dtors system, on most or all archs. some archs had already switched a long time ago. without following this change, global ctors/dtors will cease to work under musl when building with new gcc versions. the most surprising part of this patch is that it actually reduces the size of the init code, for both static and shared libc. this is achieved by (1) unifying the handling main program and shared libraries in the dynamic linker, and (2) eliminating the glibc-inspired rube goldberg machine for passing around init and fini function pointers. to clarify, some background: the function signature for __libc_start_main was based on glibc, as part of the original goal of being able to run some glibc-linked binaries. it worked by having the crt1 code, which is linked into every application, static or dynamic, obtain and pass pointers to the init and fini functions, which __libc_start_main is then responsible for using and recording for later use, as necessary. however, in neither the static-linked nor dynamic-linked case do we actually need crt1.o's help. with dynamic linking, all the pointers are available in the _DYNAMIC block. with static linking, it's safe to simply access the _init/_fini and __init_array_start, etc. symbols directly. obviously changing the __libc_start_main function signature in an incompatible way would break both old musl-linked programs and glibc-linked programs, so let's not do that. instead, the function can just ignore the information it doesn't need. new archs need not even provide the useless args in their versions of crt1.o. existing archs should continue to provide it as long as there is an interest in having newly-linked applications be able to run on old versions of musl; at some point in the future, this support can be removed.
2013-01-04__assert_fail(): remove _Noreturn, to get proper stacktracesrofl0r1-1/+1
for _Noreturn functions, gcc generates code that trashes the stack frame, and so it makes it impossible to inspect the causes of an assert error in gdb. abort() is not affected (i have not yet investigated why).
2012-09-06further use of _Noreturn, for non-plain-C functionsRich Felker2-2/+2
note that POSIX does not specify these functions as _Noreturn, because POSIX is aligned with C99, not the new C11 standard. when POSIX is eventually updated to C11, it will almost surely give these functions the _Noreturn attribute. for now, the actual _Noreturn keyword is not used anyway when compiling with a c99 compiler, which is what POSIX requires; the GCC __attribute__ is used instead if it's available, however. in a few places, I've added infinite for loops at the end of _Noreturn functions to silence compiler warnings. presumably __buildin_unreachable could achieve the same thing, but it would only work on newer GCCs and would not be portable. the loops should have near-zero code size cost anyway. like the previous _Noreturn commit, this one is based on patches contributed by philomath.
2012-09-06add _Noreturn function attribute, with fallback for pre-C11 GNUCRich Felker4-4/+4
2012-08-25add c11 quick_exit and at_quick_exit functionsRich Felker2-0/+44
2012-08-19fix bug whereby most atexit-registered functions got skippedRich Felker1-3/+2
2012-06-19stdio: handle file position correctly at program exitRich Felker1-3/+5
for seekable files, posix imposed requirements on the offset of the underlying open file description after a stream is closed. this was correctly handled (as a side effect of the unconditional fflush call) when streams were explicitly closed by fclose, but was not handled correctly at program exit time, where fflush(0) was being used. the weak symbol hackery is to pull in __stdio_exit if either of __toread or __towrite is used, but avoid calling it twice so we don't have to keep extra state. the new __stdio_exit is a streamlined fflush variant that avoids performing any unnecessary operations and which never unlocks the files or open file list, so we can be sure no other threads write new data to a stream's buffer after it's already flushed.
2012-06-14reorder exit code to defer stdio flush until after dtorsRich Felker1-4/+1
this is required in case dtors use stdio. also remove the old comments; one was cruft from when the code used to be using function pointers and conditional calls, and has little motivation now that we're using weak symbols. the other was just complaining about having to support dtors even though the cost was made essentially zero in the non-use case by the way it's done here.
2012-06-02ensure that abort always worksRich Felker1-0/+2
Per POSIX, "The abort() function shall cause abnormal process termination to occur, unless the signal SIGABRT is being caught and the signal handler does not return." If SIGABRT is blocked or if a signal handler is installed and does return, abort is still required to cause abnormal program termination. We cannot use a_crash() to do this, since a SIGILL handler could also be installed (and might even longjmp out of the abort, not expecting to be invoked from within abort), nor can we rely on resetting the signal handler and re-raising the signal (this has race conditions in multi-threaded programs). On the other hand, SIGKILL is a perfectly safe, unblockable way to obtain abnormal program termination, and it requires no ugly loop-and-retry logic.
2012-05-10remove __lock dependency from exitRich Felker1-2/+4
there's no sense in using a powerful lock in exit, because it will never be unlocked. a thread that arrives at exit while exit is already in progress just needs to hang forever. use the pause syscall for this because it's cheap and easy and universally available.
2012-04-24ditch the priority inheritance locks; use malloc's version of lockRich Felker2-9/+9
i did some testing trying to switch malloc to use the new internal lock with priority inheritance, and my malloc contention test got 20-100 times slower. if priority inheritance futexes are this slow, it's simply too high a price to pay for avoiding priority inversion. maybe we can consider them somewhere down the road once the kernel folks get their act together on this (and perferably don't link it to glibc's inefficient lock API)... as such, i've switch __lock to use malloc's implementation of lightweight locks, and updated all the users of the code to use an array with a waiter count for their locks. this should give optimal performance in the vast majority of cases, and it's simple. malloc is still using its own internal copy of the lock code because it seems to yield measurably better performance with -O3 when it's inlined (20% or more difference in the contention stress test).
2011-10-14add dummy __cxa_finalizeRich Felker1-0/+4
musl's dynamic linker does not support unloading dsos, so there's nothing for this function to do. adding the symbol in case anything depends on its presence..
2011-10-14support __cxa_atexit, and registering atexit functions from atexit handlersRich Felker1-7/+26
mildly tested; may have bugs. the locking should be updated not to use spinlocks but that's outside the scope of this one module.
2011-10-14simplify atexit and fflush-on-exit handlingRich Felker2-8/+8
2011-04-06consistency: change all remaining syscalls to use SYS_ rather than __NR_ prefixRich Felker1-2/+2
2011-03-28major stdio overhaul, using readv/writev, plus other changesRich Felker1-1/+1
the biggest change in this commit is that stdio now uses readv to fill the caller's buffer and the FILE buffer with a single syscall, and likewise writev to flush the FILE buffer and write out the caller's buffer in a single syscall. making this change required fundamental architectural changes to stdio, so i also made a number of other improvements in the process: - the implementation no longer assumes that further io will fail following errors, and no longer blocks io when the error flag is set (though the latter could easily be changed back if desired) - unbuffered mode is no longer implemented as a one-byte buffer. as a consequence, scanf unreading has to use ungetc, to the unget buffer has been enlarged to hold at least 2 wide characters. - the FILE structure has been rearranged to maintain the locations of the fields that might be used in glibc getc/putc type macros, while shrinking the structure to save some space. - error cases for fflush, fseek, etc. should be more correct. - library-internal macros are used for getc_unlocked and putc_unlocked now, eliminating some ugly code duplication. __uflow and __overflow are no longer used anywhere but these macros. switch to read or write mode is also separated so the code can be better shared, e.g. with ungetc. - lots of other small things.
2011-03-19syscall overhaul part two - unify public and internal syscall interfaceRich Felker1-3/+2
with this patch, the syscallN() functions are no longer needed; a variadic syscall() macro allows syscalls with anywhere from 0 to 6 arguments to be made with a single macro name. also, manually casting each non-integer argument with (long) is no longer necessary; the casts are hidden in the macros. some source files which depended on being able to define the old macro SYSCALL_RETURNS_ERRNO have been modified to directly use __syscall() instead of syscall(). references to SYSCALL_SIGSET_SIZE and SYSCALL_LL have also been changed. x86_64 has not been tested, and may need a follow-up commit to fix any minor bugs/oversights.
2011-02-12initial check-in, version 0.5.0v0.5.0Rich Felker5-0/+111