path: root/src/stdio/fclose.c
AgeCommit message (Collapse)AuthorLines
2018-11-02fix deadlock and buffered data loss race in fcloseRich Felker-13/+19
fflush(NULL) and __stdio_exit lock individual FILEs while holding the open file list lock to walk the list. since fclose first locked the FILE to be closed, then the ofl lock, it could deadlock with these functions. also, because fclose removed the FILE to be closed from the open file list before flushing and closing it, a concurrent fclose or exit could complete successfully before fclose flushed the FILE it was closing, resulting in data loss. reorder the body of fclose to first flush and close the file, then remove it from the open file list only after unlocking it. this creates a window where consumers of the open file list can see dead FILE objects, but in the absence of undefined behavior on the part of the application, such objects will be in an inactive-buffer state and processing them will have no side effects. __unlist_locked_file is also moved so that it's performed only for non-permanent files. this change is not necessary, but preserves consistency (and thereby provides safety/hardening) in the case where an application uses one of the standard streams after closing it while holding an explicit lock on it. such usage is of course undefined behavior.
2018-09-12reduce spurious inclusion of libc.hRich Felker-1/+1
libc.h was intended to be a header for access to global libc state and related interfaces, but ended up included all over the place because it was the way to get the weak_alias macro. most of the inclusions removed here are places where weak_alias was needed. a few were recently introduced for hidden. some go all the way back to when libc.h defined CANCELPT_BEGIN and _END, and all (wrongly implemented) cancellation points had to include it. remaining spurious users are mostly callers of the LOCK/UNLOCK macros and files that use the LFS64 macro to define the awful *64 aliases. in a few places, new inclusion of libc.h is added because several internal headers no longer implicitly include libc.h. declarations for __lockfile and __unlockfile are moved from libc.h to stdio_impl.h so that the latter does not need libc.h. putting them in libc.h made no sense at all, since the macros in stdio_impl.h are needed to use them correctly anyway.
2018-02-24remove useless null check before call to free in fcloseRich Felker-1/+1
2015-09-09fix fclose of permanent (stdin/out/err) streamsRich Felker-2/+3
this fixes a bug reported by Nuno Gonçalves. previously, calling fclose on stdin or stdout resulted in deadlock at exit time, since __stdio_exit attempts to lock these streams to flush/seek them, and has no easy way of knowing that they were closed. conceptually, leaving a FILE stream locked on fclose is valid since, in the abstract machine, it ceases to exist. but to satisfy the implementation-internal assumption in __stdio_exit that it can access these streams unconditionally, we need to unlock them. it's also necessary that fclose leaves permanent streams in a state where __stdio_exit will not attempt any further operations on them. fortunately, the call to fflush already yields this property.
2015-06-16refactor stdio open file list handling, move it out of global libc structRich Felker-3/+3
functions which open in-memory FILE stream variants all shared a tail with __fdopen, adding the FILE structure to stdio's open file list. replacing this common tail with a function call reduces code size and duplication of logic. the list is also partially encapsulated now. function signatures were chosen to facilitate tail call optimization and reduce the need for additional accessor functions. with these changes, static linked programs that do not use stdio no longer have an open file list at all.
2014-08-23fix false ownership of stdio FILEs due to tid reuseRich Felker-0/+6
this is analogous commit fffc5cda10e0c5c910b40f7be0d4fa4e15bb3f48 which fixed the corresponding issue for mutexes. the robust list can't be used here because the locks do not share a common layout with mutexes. at some point it may make sense to simply incorporate a mutex object into the FILE structure and use it, but that would be a much more invasive change, and it doesn't mesh well with the current design that uses a simpler code path for internal locking and pulls in the recursive-mutex-like code when the flockfile API is used explicitly.
2012-11-01fix more unused variable warningsRich Felker-2/+1
some of these were coming from stdio functions locking files without unlocking them. I believe it's useful for this to throw a warning, so I added a new macro that's self-documenting that the file will never be unlocked to avoid the warning in the few places where it's wrong.
2012-10-24correct locking in stdio functions that tried to be lock-freeRich Felker-2/+5
these functions must behave as if they obtain the lock via flockfile to satisfy POSIX requirements. since another thread can provably hold the lock when they are called, they must wait to obtain the lock before they can return, even if the correct return value could be obtained without locking. in the case of fclose and freopen, failure to do so could cause correct (albeit obscure) programs to crash or otherwise misbehave; in the case of feof, ferror, and fwide, failure to obtain the lock could sometimes return incorrect results. in any case, having these functions proceed and return while another thread held the lock was wrong.
2012-08-11add bsd fgetln functionRich Felker-0/+1
optimized to avoid allocation and return lines directly out of the stream buffer whenever possible.
2011-07-30add proper fuxed-based locking for stdioRich Felker-1/+1
previously, stdio used spinlocks, which would be unacceptable if we ever add support for thread priorities, and which yielded pathologically bad performance if an application attempted to use flockfile on a key file as a major/primary locking mechanism. i had held off on making this change for fear that it would hurt performance in the non-threaded case, but actually support for recursive locking had already inflicted that cost. by having the internal locking functions store a flag indicating whether they need to perform unlocking, rather than using the actual recursive lock counter, i was able to combine the conditionals at unlock time, eliminating any additional cost, and also avoid a nasty corner case where a huge number of calls to ftrylockfile could cause deadlock later at the point of internal locking. this commit also fixes some issues with usage of pthread_self conflicting with __attribute__((const)) which resulted in crashes with some compiler versions/optimizations, mainly in flockfile prior to pthread_create.
2011-05-02fix fclose return status logic, againRich Felker-1/+2
the previous fix was incorrect, as it would prevent f->close(f) from being called if fflush(f) failed. i believe this was the original motivation for using | rather than ||. so now let's just use a second statement to constrain the order of function calls, and to back to using |.
2011-05-01fix undefined call order in fclose, possible lost output depending on compilerRich Felker-1/+1
pcc turned up this bug by calling f->close(f) before fflush(f), resulting in lost output and error on flush.
2011-02-12initial check-in, version 0.5.0v0.5.0Rich Felker-0/+21